【问题标题】:why sfinae overload is not resolved为什么 sfinae 过载没有解决
【发布时间】:2018-06-06 08:47:13
【问题描述】:

这个版本很好用:

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

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

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

【问题讨论】:

  • 默认模板参数值不是函数签名的一部分
  • std::enable_if doc 中甚至还有一个关于这个常见错误的注释。

标签: c++ templates overloading sfinae


【解决方案1】:

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

【讨论】:

  • @Klaus 我修正了声明。重点是不同的表达方式
  • 谢谢!所以我记住,表达本身就不同了。感觉很奇怪,这个表达式有点像签名的一部分……但是好吧,就像它一样;)
猜你喜欢
  • 1970-01-01
  • 2021-11-06
  • 1970-01-01
  • 1970-01-01
  • 2019-02-17
  • 1970-01-01
  • 2015-05-31
  • 2016-07-06
  • 2019-01-25
相关资源
最近更新 更多