使用std ::前进,并带有非矫正,普通的旧参考

Using std::forward with a non-forwarding, plain old reference

本文关键字:参考 前进 std 使用      更新时间:2023-10-16

要求朋友:

为什么std::forward在以下代码中会将参数c铸成rvalue?

template <typename T>
void f (T& c) {
    using value_type = typename std::remove_reference_t<T>; 
    std::vector<value_type> v; 
    // debugger reveals: push_back( T&& value ) is called here  
    v.push_back(std::forward<T>(c));
}

请注意,c不是这里的通用/转发参考。我知道这样的事实是,如果实际情况确实如此,那么很可能会更有用。

要了解这种情况,您必须了解为什么转发参考可以正常工作。给定一个定义

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

之类的东西
some_type some_object;
foo(some_object);

模板推论将Tsome_type&。现在参数t具有some_type& &&类型。由于您无法参考引用,因此应用参考折叠规则,some_type& &&折叠到some_type&

如果您写的东西

some_type some_object;
foo(std::move(some_object));

模板扣除将T扣除为some_type。现在,参数t具有some_type&&类型。这是一个完全有效的类型,因此没有进行参考折叠。

现在我们到达std::forwardstd::forward<U>所做的就是将其参数投放到U&&。如果Usome_type,如上所述第二种情况,则将参数投入到some_type&&。它仍然是rvalue引用。如果Usome_type&,则如上所述,再次执行参考删除,并且some_type& &&成为some_type&。因此std::forward返回lvalue-reference。

因此,对您原始问题的最终答案是,std::forward的返回类型仅取决于传递的类型作为std::forward的模板参数。由于在您的情况下T将始终将其推论为非参考类型,因此std::forward将始终返回rvalue-Reference。

std::forward<T>(c)等于 static_cast<T&&>(c)

如果T&&是转发参考,那么这允许将LVALUE作为LVALUE转发,因为T将被推导为LVALUE参考类型,而T&&将通过参考 - 胶卷规则为相同的LVALUE参考类型。在您的情况下,T&&不是转发参考,因此这不起作用。

好吧, std::forward<T>(x)的定义是将 x铸造为type T&&。如果您将非参数作为参数传递,则将获得RVALUE参考T&&。由于您的T不能是参考类型(您不能具有对参考的参考),因此必须是非参考类型。