【问题标题】:Why adding `const` makes the universal reference as rvalue为什么添加`const`会使通用引用成为右值
【发布时间】:2016-12-13 09:16:37
【问题描述】:

我一直在阅读 Scott 关于 c++11 和 14 的最后一篇杰作中的通用引用,尽管有一个参数分配给左值或右值类型引用参数,但在两者之间有一些称为通用引用的东西可以根据传递的参数的类型特征推断为左/右值。我可以理解是什么使参数成为通用引用,但我不清楚的一件事是为什么将 const 添加到类型参数const T&& p 使 p 成为右值:

template<typename T>
void f(T&& param); // param is an universal reference

template<typename T>
void f(const T&& param); // param is an rvalue reference

const 分配给引用参数时是否比这更多?

【问题讨论】:

    标签: c++ templates c++11 c++14 forwarding-reference


    【解决方案1】:

    官方名称不是通用引用,而是forwarding referenceStandard 声明只有对 cv-unqualified 模板参数的右值引用属于此类:

    14.8.2.1 从函数调用中推导出模板参数 [temp.deduct.call]

    3 如果 P 是 cv 限定类型,则 P 类型的顶级 cv 限定符 类型推导被忽略。如果 P 是引用类型,则类型 P所指的用于类型推导。 转发参考是 对 cv 非限定模板参数的右值引用。 如果 P 是 转发引用,参数是一个左值,类型为“左值” 引用 A”代替 A 用于类型扣除。 [ 例子:

    template <class T> int f(T&& heisenreference);
    template <class T> int g(const T&&);
    int i;
    int n1 = f(i); // calls f<int&>(int&)
    int n2 = f(0); // calls f<int>(int&&)
    int n3 = g(i); // error: would call g<int>(const int&&), which
                   // would bind an rvalue reference to an lvalue
    

    —结束示例]

    允许const T&amp;&amp; 充当转发引用,将无法重载仅将右值引用作为参数的模板函数。

    更新:正如@HowardHinnant 在 cmets 中提到的那样,const T&amp;&amp; 确实有其用途(另请参阅 this Q&A)。

    【讨论】:

    • 为了与 Effective Modern C++ 中第 24 项中混淆 OP 的部分联系起来,Scott 将(松散地)通用引用描述为类型中的右值引用推断上下文。上面 14.8.2.1 标准引用中的第一句(非强调)(“如果 P 是 cv 限定类型,则 P 的类型的顶级 cv 限定符被类型推导忽略") 清楚地解释了 Scott 的声明,即 “即使是简单的 const 限定符的存在也足以使引用失去通用性”(引自本书,第 24 条)。
    • @dfri 谢谢,我附近没有 EMC++ 的数字副本。
    • 关于原因的更多动机:有时我们需要说:不要绑定到右值,只绑定到左值:template &lt;class T&gt; void cref(const T&amp;&amp;) = delete;
    • “允许 const T&& 充当转发引用,会导致将右值引用绑定到左值。”,严格来说,这是不正确的。如果允许const T&amp;&amp; 用作转发引用,我们将T 推导出为int &amp;g(i),然后折叠到const int &amp;,它将const lvalue 引用绑定到lvalue。问题是如果T &amp;&amp;const T &amp;&amp; 都被允许用作转发引用,我们将无法重载仅将右值引用作为参数的模板函数。
    • @TemplateRex 您能否展示一个简短的示例(代码)来说明为什么“允许 const T&& 充当转发引用,将无法重载仅将右值引用作为参数的模板函数” ?谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-15
    • 2020-01-23
    • 1970-01-01
    • 2019-12-11
    • 1970-01-01
    相关资源
    最近更新 更多