The code below compiles (gcc 4.7.2 or icc 13) and produces "1 2" output. Which means that const
qualifier is dropped, ie, f<int&>
has the parameter type int&
.
Why does it happen? As I understand, according to §14.3.1.4:
If a template-argument for a template-parameter
T
names a type “reference to cv1S
”, an attempt to create the type “reference to cv2T
” creates the type “reference to cv12S
”, where cv12 is the union of the cv-qualifiers cv1 and cv2 . Redundant cv-qualifiers are ignored.
const
should not be dropped. Here is the code:
#include <iostream>
using namespace std;
template <typename T>
void f(const T& t)
{
t++;
}
int main()
{
int a = 1;
cout << a;
f<int&>(a);
cout << ' ' << a << endl;
return 0;
}
GCC 4.7.2 does not compile this when the flag -std=c++98
is specified. In fact, in C++98 (as well as in C++03) references to references do not collapse.
An attempt to instantiate f<int&>
, where T = int&
, produces the following function signature (here I intentionally switch the position of the argument type T
and the const
specifier, which is allowed because const T&
is the same as T const&
):
void f(int& const& t) // ERROR: reference to reference is illegal
The above is not legal in C++98, nor in C++03. Consistently, this is the error you get from GCC 4.7.2:
Compilation finished with errors:
source.cpp: In function 'int main()':
source.cpp:15:14: error: no matching function for call to 'f(int&)'
source.cpp:15:14: note: candidate is:
source.cpp:5:6: note: template<class T> void f(const T&)
source.cpp:5:6: note: template argument deduction/substitution failed:
source.cpp: In substitution of 'template<class T> void f(const T&) [with T = int&]':
source.cpp:15:14: required from here
source.cpp:5:6: error: forming reference to reference type 'int&'
Nevertheless, if you use the -std=c++11
flag, then the compiler performs reference collapsing when instantiating the template: an lvalue reference to an lvalue reference becomes an lvalue reference:
void f(int& const& t) == void f(int& t)
Here the const
qualifier gets dropped, because it applies to the reference , and not to the referenced object. Since references cannot be reassigned, they are const
by nature, which is why the const
is considered superfluous and removed. See this Q&A on SO for an explanation.
That yields an lvalue reference to an lvalue reference, which resolves into a simple lvalue reference. Hence, the signature on the right side is instantiated.
The above is a viable candidate to resolve the call for f<int&>(a)
and, therefore, it compiles without errors.
Here is 1770 where the quote in question seems to originate:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1770.html
14.3.1 - Template type arguments
-4- If a template-argument for a template-parameter T names a type "lvalue-reference to cv1 S," an attempt to create the type "(lvalue or rvalue) reference to cv2 T" creates the type "lvalue-reference to cv12 S," where cv12 is the union of the cv-qualifiers cv1 and cv2. If the template-argument names a type "rvalue-reference to cv1 S," an attempt to create the type "lvalue-reference to cv2 T" creates the type "lvalue-reference to cv12 S." If the template-argument names a type "rvalue-reference to cv1 S," an attempt to create the type "rvalue-reference to cv2 T" creates the type "rvalue-reference to cv12 S." Redundant cv-qualifiers are ignored.
Here is 2118 where the quote has been struck out:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html
14.3.1 - Template type arguments
-4- If a template-argument for a template-parameter T names a type
"reference to cv1 S"that is a reference to a type A, an attempt to create the type"reference to cv2 T""lvalue-reference to cv T" creates the type"reference to cv12 S", where cv12 is the union of the cv-qualifiers cv1 and cv2.Redundant cv-qualifiers are ignored"lvalue-reference to A", while an attempt to create the type "rvalue-reference to cv T" creates the type T.
What you are quoting seems to be obsolete wording.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.