指定标志时,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
以上在 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
认为是多余的和删除的。有关解释,请参阅关于 SO 的此问答。
这会产生一个对左值引用的左值引用,它解析为一个简单的左值引用。因此,右侧的签名被实例化。
以上是解决调用的可行候选者f<int&>(a)
,因此它编译时没有错误。