use*_*436 6 c++ reference qualifiers c++03 c++98
下面的代码编译(gcc 4.7.2或icc 13)并产生"1 2"输出.这意味着const限定符被删除,即f<int&>具有参数类型int&.
为什么会这样?据我了解,根据§14.3.1.4:
如果一个模板参数的模板参数
T名称的类型"参考CV1S",企图制造型"参考CV2T"创造型"参考CV12S",其中CV12是CV-合格网络ERS的联合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;
}
Run Code Online (Sandbox Code Playgroud)
GCC 4.7.2并没有该标志时,编译这个-std=c++98指定的。事实上,在 C++98(以及 C++03)中,对引用的引用不会崩溃。
尝试实例化f<int&>, whereT = int&会产生以下函数签名(这里我有意切换了参数类型T和说明const符的位置,这是允许的,因为const T&与 相同T const&):
void f(int& const& t) // ERROR: reference to reference is illegal
Run Code Online (Sandbox Code Playgroud)
以上在 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&'
Run Code Online (Sandbox Code Playgroud)
尽管如此,如果您使用该-std=c++11标志,那么编译器在实例化模板时会执行引用折叠:对左值引用的左值引用变为左值引用:
void f(int& const& t) == void f(int& t)
Run Code Online (Sandbox Code Playgroud)
这里的const限定符被删除,因为它适用于引用,而不是被引用的对象。由于引用不能重新分配,它们const本质上是,这就是为什么const被认为是多余的并被删除。有关解释,请参阅SO 上的此问答。
这产生了对左值引用的左值引用,它解析为一个简单的左值引用。因此,右侧的签名被实例化。
以上是解决调用的可行候选者f<int&>(a),因此,它编译时没有错误。
这是 1770 年,有问题的引用似乎起源于:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1770.html
14.3.1 - 模板类型参数
-4- 如果模板参数 T 的模板参数将类型命名为“对 cv1 S 的左值引用”,则尝试创建类型“对 cv2 T 的(左值或右值)引用”会创建类型“左值引用”到 cv12 S”,其中 cv12 是 cv 限定符 cv1 和 cv2 的并集。如果模板参数将类型命名为“对 cv1 S 的右值引用”,则尝试创建类型“对 cv2 T 的左值引用”将创建类型“对 cv12 S 的左值引用”。如果模板参数将类型命名为“对 cv1 S 的右值引用”,则尝试创建类型“对 cv2 T 的右值引用”将创建类型“对 cv12 S 的右值引用”。冗余的 cv 限定符被忽略。
这是 2118,其中引用已被删除:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html
14.3.1 - 模板类型参数
-4- 如果模板参数 T 的模板参数将类型
“对 cv1 S的引用”命名为对类型 A 的引用,则尝试创建类型“对 cv2 T的引用”“对 cv 的左值引用” T”创建类型“对 cv12 S 的引用”,其中 cv12 是 cv 限定符 cv1 和 cv2 的并集。冗余 cv 限定符被忽略“对 A 的左值引用”,而尝试创建类型“对 cv T 的右值引用”会创建类型 T。
你所引用的似乎是过时的措辞。