【问题标题】:Why deduced types of fun(T t) and fun(T && t) are different in C++?为什么在 C++ 中推导的 fun(T t) 和 fun(T && t) 类型不同?
【发布时间】:2018-01-17 15:22:59
【问题描述】:
template <typename T>
void fun1(T t) {} 

template <typename T>
void fun2(T && t) {}

int i = 1;
fun1(i); // the deduced type of T is int
fun2(i); // the deduced type of T is int &

fun1(i)和fun2(i)中T的推导类型分别是intint &amp;,谁能解释一下编译器如何推导的机制?

更新

这个问题不是Type not deduced to be r-value reference: why not?的重复问题,因为:

后面的问题解释了以下的扣除规则:

template <class T>
void foo(T&& )

这里想了解一下扣分规则的区别

template <class T>
void foo(T&& )

template <class T>
void foo(T )

【问题讨论】:

  • 您希望得到什么? intint&amp;&amp; 都会使 t 成为右值引用,它不能绑定到左值 i
  • 不,不是。请参阅更新。 @E_net4
  • 不同之处在于它们是不同的函数签名。 fun1(T) 总是按值传递,fun2(T&amp;&amp;) 根据链接副本中解释的规则推导。它们没有其他关系。
  • 我知道 fun2(i) 是通过左值引用传递的,但是为什么 fun1(i) 是通过值传递而不是左值引用呢? @thirtythreeforty

标签: c++ rvalue-reference


【解决方案1】:

这是一个完美的正向,它可以根据提供给模板的参数产生不同的结果。

完美的转发减少了对重载函数的需求,并有助于 避免转发问题。转发问题可能发生在 您编写一个将引用作为其参数的通用函数 并将这些参数传递(或转发)给另一个函数。为了 例如,如果泛型函数采用 const T& 类型的参数, 那么被调用的函数不能修改该参数的值。如果 泛型函数接受 T& 类型的参数,然后函数 不能使用右值调用(例如临时对象或 整数字面量)。

通常,要解决这个问题,你必须提供重载 同时采用 T& 和 const T& 的通用函数的版本 它的每一个参数。结果,超载的数量 函数随着参数的数量呈指数增长。 右值引用使您能够编写函数的一个版本, 接受任意参数并将它们转发给另一个函数 如果直接调用了另一个函数。

Rvalue Reference

转发引用 转发引用是一种特殊的引用,它保留函数参数的值类别,从而可以通过 std::forward 转发它。转发引用是:

  1. 函数模板的函数参数声明为对同一函数模板的 cv 非限定类型模板参数的右值引用:
  2. auto&& 除非从大括号括起来的初始值设定项列表中推导出来。

Forwarding Reference

这里解释了它是如何做的: Template Deduction

【讨论】:

    【解决方案2】:

    因为i 的类型是int,而不是int&amp;。正如[temp.deduct.call] paragraph 1 所说

    模板参数推导是通过比较每个函数模板来完成的 参数类型(称为 P)包含​​模板参数,这些模板参数与调用的相应参数的类型(称为 A)一起参与模板参数推导,如下所述。

    [temp.deduct.call] paragraph 4

    一般来说,推导过程会尝试找到使推导的 A 与 A 相同的模板参数值(在类型 A 如上所述转换之后)。

    转发参考案例是一种特殊情况。正如[temp.deduct.call] paragraph 3 明确表示的那样

    如果 P 是转发引用且参数是左值,则使用类型“对 A 的左值引用”代替 A 进行类型推导。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-16
      • 2018-10-12
      • 2017-12-02
      • 1970-01-01
      • 1970-01-01
      • 2021-01-31
      • 2022-06-13
      相关资源
      最近更新 更多