为啥 const 模板参数不是通用/转发参考

Posted

技术标签:

【中文标题】为啥 const 模板参数不是通用/转发参考【英文标题】:Why is const template parameter not a universal/forwarding reference为什么 const 模板参数不是通用/转发参考 【发布时间】:2020-12-13 14:47:01 【问题描述】:

我正在阅读有关通用参考/转发参考和this link says 的内容:

这里的param 是通用参考

template<typename T>
void f(T&& param);   

但是这里param不是一个通用引用,它是一个右值引用

template<typename T>
void f(const T&& param);

通用引用的定义如下:

如果一个变量或参数被声明为 T&& 对于某个推导出的类型 T,则该变量或参数是一个通用引用。

我读到 T 是一个推导类型,因为 Template argument deduction。

为什么第二种情况不是通用参考?出于某种原因,const T&amp;&amp; param 的存在是否不遵循模板参数推导?如果有,为什么?

【问题讨论】:

【参考方案1】:

前言:官方术语是转发引用。

那么为什么第二种情况不是通用参考呢?

因为它是对 const 的引用。并且对 const 的引用不是转发引用。

为什么?

转发引用的全部意义在于,当将右值作为参数给出时,该参数将被推断为对非常量右值的引用,这允许在转发时移动此类参数(同时允许左值不被移出)。您不能从对 const 的引用移动,因为移动构造函数的参数将是对非 const 的右值引用,它不能绑定到对 const 的引用。

语言律师的回答是:因为标准是这样说的:

[temp.deduct.call] 转发引用是对 cv-unqualified 模板参数的右值引用,它不代表类模板的模板参数...

【讨论】:

【参考方案2】:

因为它会破坏目的。

即使它是转发引用,在传入右值时也会得到 const 右值引用。移动语义需要非 const 引用,以便可以修改源对象,因为关键在于窃取即将过期的对象,而不是做一个可能很昂贵的副本。

无论价值类别如何,您都会一直进行复制。所以在这种情况下“转发”没有意义。

【讨论】:

以上是关于为啥 const 模板参数不是通用/转发参考的主要内容,如果未能解决你的问题,请参考以下文章

模板参数的“右值引用”是转发引用

显式指定通用 lambda 的 operator() 模板参数是不是合法?

为啥 std::pair 对于 const 引用和转发引用参数有两个不同的构造函数?

何时使用函数模板而不是通用 lambda?

如何对可变参数模板函数的异构参数包进行通用计算?

如何编写以特征张量为参数的通用模板函数?