首页 > 解决方案 > 为什么 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; }
};  

此版本失败:

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()”重载

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

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

标签: c++templatesoverloadingsfinae

解决方案


因为在案例#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 有效,因为返回类型取决于模板参数并与不同的表达式一起使用;那么它们被认为是不等价的。


推荐阅读