C ++ 98/03引用折叠和cv限定符

时间:2013-02-07 21:45:18

标签: c++ reference c++03 qualifiers c++98

下面的代码编译(gcc 4.7.2或icc 13)并生成“1 2”输出。这意味着const限定符被删除,i。例如,f<int&>的参数类型为int&

为什么会这样?据我了解,根据§14.3.1.4:

  

如果模板参数T的模板参数命名类型为“ cv1 S的引用”,则尝试创建类型“对 cv2 T“创建类型”对 cv12 S的引用“,其中 cv12 是cv-quali firs的联合 cv1 cv2 。冗余的cv-quali firs被忽略。

不应删除

const。这是代码:

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

2 个答案:

答案 0 :(得分:4)

当指定标志-std=c++98时,

GCC 4.7.2会编译它。实际上,在C ++ 98(以及C ++ 03中)对引用的引用不会崩溃。

尝试实例化f<int&>,其中T = int&生成以下函数签名(这里我故意切换参数类型Tconst说明符的位置,这是允许的,因为const T&T const&}相同:

void f(int& const& t) // ERROR: reference to reference is illegal

上述内容在C ++ 98和C ++ 03中都不合法。一直以来,这是你从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&'

然而,如果使用-std=c++11标志,则编译器在实例化模板时执行引用折叠:对左值引用的左值引用变为左值引用:

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

此处const限定符被删除,因为它适用于引用,而不适用于引用的对象。由于无法重新分配引用,因此它们const本质上是const被认为是多余的并被删除的原因。有关解释,请参阅 this Q&A on SO

产生左值引用的左值引用,该引用解析为简单的左值引用。因此,右侧的签名被实例化。

以上是解决f<int&>(a)调用的可行候选者,因此编译时没有错误。

答案 1 :(得分:4)

这是1770年有问题的报价似乎来源:

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

  

14.3.1 - 模板类型参数

     

-4-如果模板参数T的模板参数命名类型&#34;左值 - 引用cv1 S,&#34;尝试创建类型&#34;(左值或右值)引用cv2 T&#34;创建类型&#34;左值 - 引用cv12 S,&#34;其中cv12是cv-qualifiers cv1和cv2的并集。如果template-argument命名一个类型&#34; rvalue-reference to cv1 S,&#34;尝试创建类型&#34;左值 - 引用cv2 T&#34;创建cv12 S的类型&#34;左值引用。&#34;如果template-argument命名一个类型&#34; rvalue-reference to cv1 S,&#34;尝试创建类型&#34; rvalue-reference to cv2 T&#34;创建cv12 S的类型&#34; rvalue-reference。&#34;冗余的cv限定符被忽略。

这是2118,其中引用已被删除:

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

  

14.3.1 - 模板类型参数

     

-4-如果模板参数T的template-argument命名类型为&#34;引用cv1 S&#34; ,这是对类型A的引用,则尝试创建类型&#34;引用cv2 T&#34; &#34; lvalue-reference to cv T&#34;创建类型&#34;引用cv12 S&#34;,其中cv12是cv-qualifiers cv1和cv2的并集。冗余的cv限定符被忽略&#34;左值 - 引用A&#34;,同时尝试创建类型&#34; rvalue-reference to cv T&#34;创建类型T。

你所引用的内容似乎是过时的措辞。