为什么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() {}
};
答案 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
部分放在返回值中。