if predicated on std::is

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?


template<typename T, typename std::enable_if<std::is_convertible<int, T>::value, T>::type>

if we were to remove the noise, would become

template<typename T, typename Something<T>::type>

which is declaring as its second parameter a non-type parameter, the typename here is specifying the nested type is a name of a type. See here for more information.

In the first case, the second parameter is non-type, so the function call func(3) doesn't fit the template which is expecting func<int, some_int>(3) .

链接地址: http://www.djcxy.com/p/90144.html

上一篇: std :: function vs模板

下一篇: 如果以std :: is为基础的话