C++:显式指定引用类型作为类型参数的模板函数

Гри*_*ков 3 c++ function-templates

我在玩 C++ 模板类型推导并设法编译了这个小程序。

template<typename T>
 void f(const T& val)
 {
   val = 1;
 }


 int main()
 {
    int i = 0;
    f<int&>(i);
 }
Run Code Online (Sandbox Code Playgroud)

它可以在所有主要编译器上编译,但我不明白为什么。为什么可以f赋值val,什么时候val显式标记const?它是这些编译器中的错误还是根据 C++ 标准的有效行为?

T.C*_*.C. 5

§8.3.2 [dcl.ref]/p6:

如果typedef-name (7.1.3, 14.1) *decltype-specifier (7.1.6.2) 表示类型 TR 是对类型 T 的引用,则尝试创建类型“对 cv TR 的左值引用”会创建类型“对 T 的左值引用”,而尝试创建类型“对 cv TR 的右值引用”会创建类型 TR。

这称为引用折叠,并在 C++11 中引入。在 C++03 中,您的代码格式不正确,但一些编译器支持将其作为扩展。

请注意,在 中const T &, theconst适用于 type T,因此当Tis 时int &, theconst将适用于引用类型本身(这毫无意义,因为引用无论如何都是不可变的),而不是引用的类型。这就是参考折叠规范忽略 上的任何 cv 限定符的原因TR


*模板类型参数是typedef-name,根据 §14.1 [temp.param]/p3:

类型参数其标识符不遵循省略号限定其标识符是一个的typedef名称(如果与声明 classtypename或)模板的名称(如果与声明 template在模板声明的范围)。