lundi 3 juin 2019

SFINAE with enable_if and overloading

I've done some looking around, but was unable to find a solution to my specific problem.

I have the code:

template <typename T>
typename std::enable_if<std::is_arithmetic<T>::value || std::is_enum<T>::value, std::string>::type
    convertToString(const T argument) { return std::to_string(argument); }

std::string convertToString(std::string string);

What the code is supposed to do: Use the template version for any numeric type (int, float, double and also ENum) and use the std::string version for anything else.

The code itself compiles fine, however when I pass the function a class, which has a operator const char * overload (which is a viable constructor for std::string), it throws me the following bulk of messages:

no matching function for call to 'SQL_Connection::convertToString(ClassName &)’

candidate: template<class T> typename std::enable_if<(std::is_arithmetic<_Tp>::value || std::is_enum<_Tp>::value), std::__cxx11::basic_string<char> >::type convertToString(T)
 convertToString(const T argument) { return std::to_string(argument); }
 ^~~~~~~~~~~~~~~

template argument deduction/substitution failed:
In substitution of ‘template<class T> typename std::enable_if<(std::is_arithmetic<_Tp>::value || std::is_enum<_Tp>::value), std::__cxx11::basic_string<char> >::type convertToString(T) [with T = ClassName]’:

I've been trying to wrap my head around enable_if and what it does, but at this point I find myself stumped.

Why isn't it falling back to the std::string overload, when it clearly is neither arithmetic nor an ENum?

If I explicitly convert the object to string or const char *, it works as expected.

Thank you very much for your help.

Additional info: I'm using C++11 and g++ 7.3.0 on an Ubuntu system.

Aucun commentaire:

Enregistrer un commentaire