The return type must be the same and fixed for one function or one instantiation of function template. You can make the function template as
template <typename R>
std::function<R(const std::string&)> create()
{
if(std::is_same<R, int>::value) {
return [](const std::string &value){return std::stoi(value);};
} else if(std::is_same<R, float>::value) {
return [](const std::string &value){return std::stof(value);};
} else {
throw std::runtime_error("");
}
}
then use it like
auto f_int = create<int>();
auto f_float = create<float>();
Since C++17 you can use constexpr if, the unnecessary statement would be discarded at compile-time.
template <typename R>
std::function<R(const std::string&)> create()
{
if constexpr (std::is_same_v<R, int>) {
return [](const std::string &value){return std::stoi(value);};
} else if constexpr (std::is_same_v<R, float>) {
return [](const std::string &value){return std::stof(value);};
} else {
throw std::runtime_error("");
}
}
BTW: As the return type the parameter of the std::function should be const std::string&. And the lambda seems no need to capture anything.
BTW2: Depending on how you use the return value, returning the lambda directly instead of wrapping it into std::function might be sufficient too.
template <typename R>
auto create()
{
if constexpr (std::is_same_v<R, int>) {
return [](const std::string &value){return std::stoi(value);};
} else if constexpr (std::is_same_v<R, float>) {
return [](const std::string &value){return std::stof(value);};
} else {
throw std::runtime_error("");
}
}