C++98/03 reference collapsing and cv qualifiers

后端 未结 2 793
忘掉有多难
忘掉有多难 2021-01-18 06:50

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 ha

2条回答
  •  感动是毒
    2021-01-18 07:28

    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, 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 void f(const T&)
    source.cpp:5:6: note:   template argument deduction/substitution failed:
    source.cpp: In substitution of 'template 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(a) and, therefore, it compiles without errors.

提交回复
热议问题