为什么sfinae超载没有解决

Kla*_*aus 10 c++ templates overloading sfinae

这个版本工作正常:

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; }
};  
Run Code Online (Sandbox Code Playgroud)

此版本失败:

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; }
};
Run Code Online (Sandbox Code Playgroud)

有:

错误:'模板模板V Foo2 :: bar()'不能用'模板模板V Foo2 :: bar()'重载

两个版本之间的区别是在第一个我直接使用表达式,在第二个我创建模板默认参数并使用那个作为返回类型.

在第二个例子中失败的原因是什么?

son*_*yao 7

因为在#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; }
Run Code Online (Sandbox Code Playgroud)

如你所见,它们实际上是等价的.

(强调我的)

如果两个函数模板被认为是等效的

  • 它们在同一范围内声明
  • 他们有相同的名字
  • 他们有相同的模板参数列表
  • 在返回类型和参数列表中涉及模板参数的表达式是等效的

情况#1有效,因为返回类型依赖于模板参数并与不同的表达式一起使用; 然后他们被认为是不相同的.