Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference collapsing and const [duplicate]

Consider this program:

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
}

In the above, if Foo is instantiated as Foo<double> , then things are fine, but if it is instantiated as Foo<double&>, then the call to foo becomes ambiguous. Is ref collapsing at play here when deducing the param types for foo and if so why is constness being ignored?

like image 795
MK. Avatar asked Oct 18 '22 09:10

MK.


1 Answers

Lets see what happens if we try to instatiate the Foo class template:

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

with template parameter double&. Substituting T with double& and according to reference collapsing rules you would get:

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

Since references are inherently constant double& const is equivalent to double&. Thus, you get the following instatiation:

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

Here comes the compiler shouting "Dude you can't overload foo with the same signature".

A more consise error is given by CLANG:

error: multiple overloads of 'foo' instantiate to the same signature 'void (double &&)' void foo(T&) { }

Live Demo

like image 80
101010 Avatar answered Nov 03 '22 18:11

101010