代码之家  ›  专栏  ›  技术社区  ›  Klaus

为什么sfinae过载没有解决

  •  10
  • Klaus  · 技术社区  · 7 年前

    此版本工作正常:

    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; }
    };
    

    用:

    错误:“template template v foo2::bar()”不能重载为“template template v foo2::bar()”

    两个版本的区别在于第一个版本直接使用表达式,第二个版本创建模板默认参数并将其用作返回类型。

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

    1 回复  |  直到 7 年前
        1
  •  7
  •   songyuanyao    7 年前

    因为在第二种情况下 bar 被认为是等价的。什么时候? consider whether two function templates are equivalent or not ,将忽略默认模板参数;它们不是函数模板签名的一部分。所以他们被认为

    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可以工作,因为返回类型依赖于模板参数并与不同的表达式一起使用;那么它们就被认为是不等价的。