Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the const in a const T& parameter disappear when T is a reference type? [duplicate]

The following code shows that if a template taking a ref-to-const parameter is instantiated with a reference type (e.g., int&), the parameter isn't const:

#include <iostream>

template<typename T>
void f(const T& arg)         // arg isn't const if T is a reference type
{
  arg = -1;
}

int main()
{
  int x = 0;
  f<int&>(x);                // instantiate f with reference type
  std::cout << x << '\n';    // prints -1 under gcc, clang, and msvc
}

What's going on here?

My guess is that the initial type of arg is int & const & and that this somehow transforms to int&. If that's so, exactly how does that happen, in terms of the standard? If that's not what's going on, what is?

like image 619
KnowItAllWannabe Avatar asked Jan 01 '15 01:01

KnowItAllWannabe


2 Answers

Thanks to Vlad from Moscow's answer to C++: template function with explicitly specified reference type as type parameter, I believe the crux of the const-disappearance is [dcl.ref], which says:

In a declaration T D where D has either of the forms

& attribute-specifier-seqopt D1
&& attribute-specifier-seqopt D1

and the type of the identifier in the declaration T D1 is “derived-declarator-type-list T”, then the type of the identifier of D is “derived-declarator-type-list reference to T.” The optional attribute-specifier-seq appertains to the reference type. Cv-qualified references are ill-formed except when the cv-qualifiers are introduced through the use of a typedef-name ([dcl.typedef], [temp.param]) or decltype-specifier ([dcl.type.simple]), in which case the cv-qualifiers are ignored.

I've emboldened the relevant text. (I'd like to format the entire paragraph as it is in the standard, but I can't figure out how to get the right indentation and to add subscripting.)

Once the const disappears, normal reference collapsing kicks in as usual.

like image 98
KnowItAllWannabe Avatar answered Nov 05 '22 14:11

KnowItAllWannabe


A const T is a object of type T whose value cannot be modified. However, when T is a reference type, the const modifier is superfluous since references cannot be changed once initialized - they always refer to the same object. Thus, a const T when T=int& is just a T(which in this case is int&). Thus, the argument that f<int&> takes is a lvalue reference to an int&, which by c++11's collapsing rules is just int&.

like image 3
Pradhan Avatar answered Nov 05 '22 14:11

Pradhan