This is an example of practice std :: enable_if, std :: is_same and std :: decay of.
Generic string used for conversion of far-fetched, in fact, with this specialized function template may be more appropriate.
As for when to use std :: enable_if see "C ++ Programming Language" meta-programming speak std :: enable_if there is a more appropriate example.
#include <string>
#include <type_traits>
namespace detail {
template<class T, class Enable = void>
struct ConvertToNumeric
{
T operator()(const std::string& str) const
{
return std::stoi(str);
}
};
//special cases
template< bool B, class T>
using T_enable_if_t = typename std::enable_if<B,T>::type;
template<class U, class T>
using T_same_enable_t = T_enable_if_t<std::is_same<T,U>::value, T>;
template<class T>
struct ConvertToNumeric<T, T_same_enable_t<long, T>>
{
long operator()(const std::string& str) const
{
return std::stol(str);
}
};
template<class T>
struct ConvertToNumeric<T, T_same_enable_t<unsigned long, T>>
{
unsigned long operator()(const std::string& str) const
{
return std::stoul(str);
}
};
template<typename T>
struct ConvertToNumeric<T, T_same_enable_t<long long, T>>
{
long long operator()(const std::string& str) const
{
return std::stoll(str);
}
};
template<typename T>
struct ConvertToNumeric<T, T_same_enable_t<unsigned long long, T>>
{
unsigned long long operator()(const std::string& str) const
{
return std::stoull(str);
}
};
template<typename T>
struct ConvertToNumeric<T, T_same_enable_t<float, T>>
{
float operator()(const std::string& str) const
{
return std::stof(str);
}
};
template<typename T>
struct ConvertToNumeric<T, T_same_enable_t<double, T>>
{
double operator()(const std::string& str) const
{
return std::stod(str);
}
};
template<typename T>
struct ConvertToNumeric<T, T_same_enable_t<long double, T>>
{
long double operator()(const std::string& str) const
{
return std::stold(str);
}
};
}
//this complex way, also use function template specialization
/*****************************************/
/*
template<typename T>
inline T str_to_numeric(const std::string& str)
{
return std::stoi(str);
}
template<>
inline long str_to_numeric<long>(const std::string& str)
{
return std::stol(str);
}
...
*/
template<typename T>
inline T str_to_numeric(const std::string& str)
{
using T_decay_t = typename std::decay<T>::type;
return detail::ConvertToNumeric<T_decay_t, T_decay_t>()(str);
}