Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Question about C++0x reference collapse

Tags:

c++

c++11

I don't know why these code can't be compiled. I'v tested in Visual c++ 2010 and gcc with -std=c++0x. anyone give some suggestion? thanks!

template<typename T>
class Foo
{
public:
 void test(const T&){cout<<"const";}
 void test(      T&){cout<<"non const";}
};

int main()
{
 int a;
 Foo<int&> f;
}

compile error: 'void Foo::test(T)' : member function already defined or declared

but why this can be compiled?

template<typename T> void foo(const T&){cout<<"const"; }
template<typename T> void foo( T&){cout<<"non const"; }
int main()
 {
    int a; 
    foo<int&>(a);
 }

i'v read c++0x article said: T& & ==T& , so const T& & == const T& ?

like image 722
jrry7 Avatar asked Dec 13 '10 01:12

jrry7


3 Answers

i'v read c++0x article said: T& & ==T& , so const T& & == const T& ?

Actually, that doesn't make a lot of sense. IMHO, it's better to put this into a table:

T       T&      const T      const T&
---------------------------------------
int     int&    const int    const int&
int&    int&    int&         int&
        (1)     (2)          (1+2)

1: Reference collapsing in action
2: const applies to the reference and is therefore ignored

If T is already a reference (2nd row) the const in const T applies to the reference and not to the referee. But a reference is inherently constant in the sense that you cannot make it refer to another object after initialization, so a const is just ignored here. You can think of it as "const collapsing". ;-)

like image 181
sellibitze Avatar answered Oct 04 '22 17:10

sellibitze


This:

Foo<int&> f;

gives rise to this instantiation:

class Foo<int&>
{
public:
 void test(int&);
 void test(int&);
};

const applied to a type that is a reference is a no-op. Compare it with a non-static member function operating on a reference data member:

struct A {
  int &ref;

  // valid: const member function doesn't treat "ref" as "const int&". 
  void operate() const {
    ref = 0;
  }
};

You have to pass int to Foo<...> to achieve your goal.

like image 43
Johannes Schaub - litb Avatar answered Oct 04 '22 16:10

Johannes Schaub - litb


For the second question, the two instantiated functions have the same parameter type, and both are templates (if one is a template, the other is a non-template function, the overload resolution will choose the later one), so the overload resolution will choose the template which is more specialized. Generally const T& is a more specialized type than T&, so the first template function is called.

like image 33
Cosyn Avatar answered Oct 04 '22 16:10

Cosyn