Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: template function with explicitly specified reference type as type parameter

I was playing with C++ template type deduction and managed to compile this little program.

template<typename T>
 void f(const T& val)
 {
   val = 1;
 }


 int main()
 {
    int i = 0;
    f<int&>(i);
 }

It compiles on all major compilers but I do not understand why. Why can f assign to val, when val is explicitly marked const? Is it bug in these compilers or is it valid behavior according to the C++ standard?

like image 514
Григорий Шуренков Avatar asked Jan 10 '23 08:01

Григорий Шуренков


1 Answers

§8.3.2 [dcl.ref]/p6:

If a typedef-name (7.1.3, 14.1)* or a decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a type T, an attempt to create the type “lvalue reference to cv TR” creates the type “lvalue reference to T”, while an attempt to create the type “rvalue reference to cv TR” creates the type TR.

This is known as reference collapsing and is introduced in C++11. In C++03, your code would be ill-formed, but some compilers supported it as an extension.

Note that in const T &, the const applies to the type T, so when T is int &, the const would apply to the reference type itself (which is meaningless as references are immutable anyway), not the type referred to. This is why the reference collapsing specification ignores any cv-qualifiers on TR.


*A template type parameter is a typedef-name, per §14.1 [temp.param]/p3:

A type-parameter whose identifier does not follow an ellipsis defines its identifier to be a typedef-name (if declared with class or typename) or template-name (if declared with template) in the scope of the template declaration.

like image 160
T.C. Avatar answered Jan 17 '23 18:01

T.C.