这个版本工作正常:
template<typename T>
struct Foo
{
template<typename U = T>
typename std::enable_if<std::is_same<U,A>::value>::type
bar() { std::cout << "1" << std::endl; }
template<typename U = T>
typename std::enable_if<std::is_same<U,B>::value>::type
bar() { std::cout << "2" << std::endl; }
};
此版本失败:
template<typename T>
struct Foo2
{
template<typename U = T, typename V = typename std::enable_if<std::is_same<U,A>::value>::type >
V bar() { std::cout << "1" << std::endl; }
template<typename U = T, typename V = typename std::enable_if<std::is_same<U,B>::value>::type >
V bar() { std::cout << "2" << std::endl; }
};
跟:
错误:"模板模板 V Foo2::bar((">不能被"模板模板 V Foo2::bar(("重载
两个版本之间的区别在于第一个我直接使用表达式,在第二个版本中我创建一个模板默认参数并使用该参数作为返回类型。
在第二个示例中失败的原因是什么?
因为在案例 #2 中,这两个bar
被认为是等效的。在考虑两个函数模板是否等效时,将忽略默认模板参数;它们不是函数模板签名的一部分。所以他们被认为是
template<typename U, typename V>
V bar() { std::cout << "1" << std::endl; }
template<typename U, typename V>
V bar() { std::cout << "2" << std::endl; }
如您所见,它们实际上是等效的。
(强调我的(
两个函数模板被视为等效,如果
- 它们在同一范围内声明
- 他们有相同的名称
- 它们具有相同的模板参数列表
- 在返回类型和参数列表中涉及模板参数的表达式是等效的
case#1 之所以有效,是因为返回类型依赖于模板参数并与不同的表达式一起使用;然后它们被认为是不等效的。