【问题标题】:C++ Universal Reference and type deduction of LRef parameterC++通用引用和LRef参数的类型推导
【发布时间】:2019-03-17 22:19:02
【问题描述】:

假设我们有一些代码

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

int x = 5;
// deduced Foo<int&>(int&).
// Argument type A = int. T = int&.
Foo(x);     

int& rx = x;
// deduced Foo<int&>(int& &&) -> Foo<int&>(int&).
// But... argument type A = int&, an lvalue reference to int.
// Is T = int& or under the hood it is T = int& &?
Foo(rx);

根据https://en.cppreference.com/w/cpp/language/template_argument_deduction

4) 如果 P 是对 cv 不合格模板参数的右值引用(所谓的转发引用),并且对应的函数调用参数是左值,则使用对 A 的类型左值引用代替 A 进行推导

我想知道的是:'引用折叠'规则是否应用于推导类型 T(而不是 P,参数类型)?

那么我们真的有 for 'Foo(rx)' T = int& &,它折叠成 T = int& 吗?

【问题讨论】:

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


    【解决方案1】:

    请注意,实际上,出于所有技术目的,表达式的类型永远不会被视为引用类型。 [expr.type]/1:

    如果表达式最初的类型为“引用T”([dcl.ref],[dcl.init.ref]),则在进行任何进一步分析之前,将类型调整为T

    一个值得注意的例外是decltype() 应用于未加括号的名称或类成员访问表达式。虽然语法将名称视为表达式,但语义结果涉及名称的声明类型而不是表达式的类型和值类别。

    所以在您的示例中,xint 类型的左值,rxint 类型的左值。在声明和初始化之后,语言在它们之间根本没有区别,除非你再次使用 decltype(x)decltype(rx)

    这意味着Foo(rx) 的模板类型推导与Foo(x) 的工作方式完全相同:A 的类型是int,而不是int&amp;,并且参数是一个左值。根据你引用的规则,T 被推导出为int&amp;,当将T=int&amp; 替换为函数类型时,引用折叠规则说T&amp;&amp;int&amp;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-08
      • 2011-08-01
      • 2021-03-05
      • 1970-01-01
      • 2018-03-15
      • 1970-01-01
      • 1970-01-01
      • 2011-10-07
      相关资源
      最近更新 更多