C++98/03 reference collapsing and cv qualifiers

此生再无相见时 提交于 2019-12-01 17:00:40

问题


The code below compiles (gcc 4.7.2 or icc 13) and produces "1 2" output. Which means that const qualifier is dropped, i. e., 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 cv1 S”, an attempt to create the type “reference to cv2 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.

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;
}

回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/14761581/c98-03-reference-collapsing-and-cv-qualifiers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!