参考折叠和常量

时间:2017-07-04 17:29:46

标签: c++ c++14 type-deduction

考虑这个程序:

template<typename T>
struct Foo
{
    void foo(const T&) {}   
    void foo(T&) {}
};


int main()
{
    Foo<double&> f;   
    double d = 3.14;
    f.foo(d);   //complains that foo() is ambigous
}

在上面,如果Foo被实例化为Foo<double>,那么事情很好,但如果它被实例化为Foo<double&>,则对foo的调用变得模糊不清。在推导foo的参数类型时,ref是否正在崩溃?如果是这样,为什么常量被忽略?

1 个答案:

答案 0 :(得分:3)

让我们看看如果我们尝试实例化Foo类模板会发生什么:

template<typename T>
struct Foo {
  void foo(T const&) {}   
  void foo(T&) {}
};

使用模板参数double&。用double&代替T并根据参考折叠规则得到:

struct Foo {
  void foo(double& const) {}   
  void foo(double&) {}
};

由于引用本质上是常数double& const等同于double&。因此,您将获得以下实例:

struct Foo {
  void foo(double&) {}   
  void foo(double&) {}
};

编译器大喊“你不能用相同的签名重载foo”。

CLANG给出了一个更简洁的错误:

  

错误:'foo'的多次重载实例化到同一个签名   'void(double&amp;&amp;)'void foo(T&amp;){}

Live Demo