std :: enable_if基于std :: is_convertible而不是正确推导模板

时间:2017-07-07 15:42:43

标签: c++ enable-if

我有以下代码:

#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;
}

使用此代码,我预计第一次调用func打印3(因为int确实可以转换为int,应该调用第一个专门化)第二次调用func打印TestTest()不能转换为int,因此应调用第二个专门化。但是,我得到了一个编译器错误:

  

prog.cpp:在函数'int main()'中:

     

prog.cpp:27:8:错误:没有匹配函数来调用'func(int)'

     

prog.cpp:5:6:注意:candidate:template [class T,typename std :: enable_if [std :: is_convertible [int,T&gt; :: value,T&gt; :: type&gt; void func(T)

     

prog.cpp:5:6:注意:模板参数扣除/替换失败:

     

prog.cpp:27:8:注意:无法推断模板参数'[anonymous&gt;'

但是,如果我将模板化函数更改为(同时保留其他所有内容完全相同):

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();
}

然后一切都按照我的预期进行编译和工作。这个额外的语法是什么,我为什么需要它呢?

1 个答案:

答案 0 :(得分:5)

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

如果我们要消除噪音,就会变成

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

将第二个参数声明为非类型参数,此处typename指定嵌套type是类型的名称。有关详细信息,请参阅here

在第一种情况下,第二个参数是非类型的,因此函数调用func(3)不适合期望func<int, some_int>(3)的模板。

相关问题