SFINAE用于类成员函数(一个编译另一个不成功)

时间:2015-07-25 11:18:31

标签: c++ templates c++11 sfinae

为什么class A编译而class B没有编译,编译器抱怨有两个声明,是不是都依赖SFINAE? 在使用foo

时,两者都应该使用模板类型推导

所以真正的问题是,这两个版本中的细微差别是什么 为什么class A成功使用了sfinae ......?

  • A类使用值默认(零)匿名(不必要)非类型 模板参数
  • B类使用类型默认(使用enable_if)匿名 类型模板参数

代码:

template<typename T>
struct A
{

    template<typename U, 
             typename std::enable_if<!std::is_floating_point<U>::value>::type * = nullptr
            >
    void foo() {}

    template<typename U, 
             typename std::enable_if<std::is_floating_point<U>::value>::type * = nullptr
            >
    void foo() {}
};

template<typename T>
struct B
{

    template<typename U, 
             typename = typename std::enable_if<!std::is_floating_point<U>::value>::type
            >
    void foo() {}

    template<typename U, 
             typename = typename std::enable_if<std::is_floating_point<U>::value>::type
            >
    void foo() {}
};

现场代码:http://coliru.stacked-crooked.com/a/40ec5efc7ba2a47c

2 个答案:

答案 0 :(得分:3)

class B中,foo都有相同的签名(即使它们的默认值不同):

template <typename U, typename Dummy>
void foo();

B类的错误。

在A类中,类型在字面上是不同的(即使它们都以void结尾)

答案 1 :(得分:2)

§1.3.22定义了函数模板的签名:

  

签名
<类成员函数模板>名称,参数类型列表(8.3.5),函数所属的类,   cv-qualifiers(如果有的话),ref-qualifier(如果有的话),返回类型和   模板参数列表

模板参数列表不包含给定的默认参数。对于A::foo,模板参数不等效(在§14.5.6.1中精确定义的术语)。在B::foo,他们是。您只是使用不同的默认参数声明相同的函数模板 - 从而违反了§9.2/ 1和§14.1/ 12。

仅在enable_if的条件下重载函数模板时,这是一个常见问题。特别是对于构造函数,您不能将enable_if部分放在返回值中。