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

C++: template function with explicitly specified reference type as type parameter

本文关键字:类型参数 函数 引用类型 C++      更新时间:2023-10-16

我正在玩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:

如果是 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 &中,const适用于类型T,所以当T int &时,const将应用于引用类型本身(这是没有意义的,因为引用无论如何都是不可变的(,而不是引用的类型。这就是为什么参考折叠规范忽略TR上的任何 cv 限定符。


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

标识符不跟在省略号后面的类型参数 将其标识符定义为 typedef-name(如果声明为 classtypename(或模板名称(如果声明为 template ( 在模板声明的范围内。

我想在其他

帖子中引用以下来自C++标准(8.3.2 参考文献(

1... Cv 限定引用的格式不正确,除非通过使用 typedef-name (7.1.3, 14.1( 或特定于 decltype 的 (7.1.6.2(,在这种情况下,将忽略 cv 限定符。

[ Example:
typedef int& A;
const A aref = 3; // ill-formed; lvalue reference to non-const initialized with rvalue

在上面来自 C++ 标准的示例中,最后一个语句不会被编译,因为限定符 const 被忽略(根据引用(,并且您不能将右值与非 const 引用绑定。

const T&在此

示例中不会变成int&:在f<int&>(i)中,您将T显式设置为int&。 只有当T的定义用于确定val的类型时,const才会进入图片,这变得const int&(一个微妙之处是引用在此替换过程中折叠,因此您不会在类型中出现两个&(。