SFINAE for class 成员函数(一个编译另一个不编译)

SFINAE for class member function (one compiles the other not)

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

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

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

代码:

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

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

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

所以 class B.

的错误

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

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

signature
<class member function template> name, parameter type list (8.3.5), class of which the function is a member, cv-qualifiers (if any), ref-qualifier (if any), return type, and template parameter list

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

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