I have the following code:
#include <iostream>
#include <type_traits>
template <typename T, typename std::enable_if
<std::is_convertible<int, T>::value, T>::type>
void func(T a)
{
std::cout << a << std::endl;
}
template <typename T, typename std::enable_if
<!std::is_convertible<int, T>::value, T>::type>
void func(T a)
{
a.print();
}
class Test
{
public:
void print()
{
std::cout << "Test" << std::endl;
}
};
int main()
{
func(3);
func("Test");
return 0;
}
With this code, I expected the first call to func to print out 3 (as int is indeed convertible to int, the first specialization should be called) and the second call to func to print out Test (Test() is not convertible to int, so the second specialization should be called). However, I instead get a compiler error:
prog.cpp: In function ‘int main()’:
prog.cpp:27:8: error: no matching function for call to ‘func(int)’
prog.cpp:5:6: note: candidate: template [class T, typename std::enable_if[std::is_convertible[int, T>::value, T>::type > void func(T)
prog.cpp:5:6: note: template argument deduction/substitution failed:
prog.cpp:27:8: note: couldn't deduce template parameter ‘[anonymous>’
If, however, I change the templated functions to instead be (while leaving everything else exactly the same):
template <typename T, typename std::enable_if
<std::is_convertible<int, T>::value, T>::type* =
nullptr>
void func(T a)
{
std::cout << a << std::endl;
}
template <typename T, typename std::enable_if
<!std::is_convertible<int, T>::value, T>::type* =
nullptr>
void func(T a)
{
a.print();
}
then everything compiles and works as I expected. What is this extra syntax doing and why do I need it?