C ++ 98/03 referenced links and cv qualifiers

The code below compiles (gcc 4.7.2 or icc 13) and produces the output "1 2". This means that the const discarded, i.e. e., f<int&> has the parameter type int& .

Why is this happening? As far as I understand, according to §14.3.1.4:

If the template argument to the template parameter T calls the type cv1 S link, trying to create the cv2 T link type creates the cv12 S link type, where cv12 is the union of cv-quali fiers cv1 and cv2. Excessive cv-quali fiers are ignored.

const should not be discarded. 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; } 
+6
source share
2 answers

GCC 4.7.2 does not fail when the -std=c++98 flag is -std=c++98 . In fact, in C ++ 98 (as in C ++ 03) links to links are not destroyed.

Trying to create an instance f<int&> , where T = int& , yields the following function signature (here I intentionally switch the position of the type of the argument T and the qualifier const , which is allowed, since const T& 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. Consequently, 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&' 

However, if you use the -std=c++11 flag, then the compiler collapses the links when creating the template instance: the lvalue link to the lvalue link becomes the lvalue link:

 void f(int& const& t) == void f(int& t) 

Here the const qualifier is discarded because it is applied to the link , not to the reference object. Since links cannot be reassigned, they are const in nature, therefore const is considered redundant and remote. See this Q&A on SO for an explanation.

This gives the lvalue link to the lvalue link, which resolves into a simple lvalue reference. Therefore, a signature on the right side is created.

The above is a viable candidate for call resolution for f<int&>(a) and therefore it compiles without errors.

+4
source

Here is 1770, where the quote appears to be:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1770.html

14.3.1 - Pattern Type Arguments

-4- If the template argument for the template parameter T calls the type "lvalue-reference to cv1 S", an attempt to create a type (lvalue or rvalue) reference to cv2 T "creates the type" lvalue-reference to cv12 S ", where cv12 is the union of cv qualifiers cv1 and cv2. If the template argument calls the 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 calls the 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 was struck out:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html

14.3.1 - Pattern Type Arguments

-4- If the template argument for the template parameter T calls the type “reference to cv1 S” , which is a reference to type A, an attempt to create the type “reference to cv2 T” “lvalue-reference to cv T” creates a reference of type “to cv12 S "where cv12 is the union of the cv qualifiers cv1 and cv2. Redundant cv qualifiers are ignored by "lvalue-reference to cv T" and attempting to create a type of "rvalue-reference to cv T" creates a type T.

What you quote seems to be an outdated wording.

+4
source

All Articles