我在玩 C++ 模板类型推导并设法编译了这个小程序。
template<typename T>
void f(const T& val)
{
val = 1;
}
int main()
{
int i = 0;
f<int&>(i);
}
它可以在所有主要编译器上编译,但我不明白为什么。为什么 f
可以赋值给 val
,而 val
被显式标记为 const
?它是这些编译器中的错误还是符合 C++ 标准的有效行为?
最佳答案
§8.3.2 [dcl.ref]/p6:
If a typedef-name (7.1.3, 14.1)* or a decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a type T, an attempt to create the type “lvalue reference to cv TR” creates the type “lvalue reference to T”, while an attempt to create the type “rvalue reference to cv TR” creates the type TR.
这称为引用折叠,在 C++11 中引入。在 C++03 中,您的代码可能格式错误,但一些编译器支持它作为扩展。
请注意,在 const T &
中,const
适用于类型 T
,因此当 T
是int &
,const
将应用于引用类型本身(这毫无意义,因为引用无论如何都是不可变的),而不是引用的类型。这就是为什么引用折叠规范会忽略 TR
上的任何 cv 限定符。
*根据 §14.1 [temp.param]/p3,模板类型参数是一个typedef-name:
A type-parameter whose identifier does not follow an ellipsis defines its identifier to be a typedef-name (if declared with
class
ortypename
) or template-name (if declared withtemplate
) in the scope of the template declaration.
关于C++:具有明确指定的引用类型作为类型参数的模板函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27256516/