为什么要编译:
class Testable {
public:
template <bool flag>
typename std::enable_if<flag>::type
void foo() { cout << "Yay" << endl; }
template <bool flag>
typename std::enable_if<!flag>::type
void foo() { cout << "Nay" << endl; }
};
但是如果我使用默认类型定义两个foos,那就不行了:
template <bool flag, typename = typename std::enable_if<flag>::type>
void foo() { cout << "Yay" << endl; } // (A)
template <bool flag, typename = typename std::enable_if<!flag>::type>
void foo() { cout << "Nay" << endl; } // (B)
我收到此错误(第一行指向(B)
的定义,第二行指向(A)
):
error: 'template<bool flag, class> void Testable::foo()' cannot be overloaded
error: with 'template<bool flag, class>> void Testable::foo()'
答案 0 :(得分:6)
编译器抱怨,因为两个函数模板具有相同的签名。 C ++ 11标准的第1.3.18段规定了函数模板的签名定义为:
<function template>
名称,参数类型列表(8.3.5),封闭命名空间(如果有),返回类型和 模板参数列表
如您所见,默认模板参数不是签名的一部分。
您可以通过更改Testable
的定义来解决此问题,如下所示:
class Testable {
public:
template <bool flag, typename std::enable_if<flag>::type* = nullptr>
void foo() { cout << "Yay" << endl; } // (A)
template <bool flag, typename std::enable_if<!flag>::type* = nullptr>
void foo() { cout << "Nay" << endl; } // (B)
};
答案 1 :(得分:0)
如上所述,两个函数不能具有相同的签名。
但是,我有一个不同的解决方法。
template<std::size_t>
struct secret_enum { enum class type {}; };
template<bool b, std::size_t n=0>
using EnableIf = typename std::enable_if< b, typename secret_enum<n>::type >::type;
class Testable {
public:
template <bool flag, EnableIf<flag, 0>...>
void foo() { cout << "Yay" << endl; } // (A)
template <bool flag, EnableIf<!flag, 1>...>
void foo() { cout << "Nay" << endl; } // (B)
};
使用0
,1
等枚举您的重载,生成可能的类型,然后...
说“0或更多这些”,以及类型生成enum
实例基本上是不可能的。
可悲的是,这在clang 3.2中不起作用。它在gcc 4.8中。