使用std :: forward和非转发的普通旧引用

问题描述 投票:-1回答:3

问朋友:

为什么以下代码中的std::forward将参数c强制转换为右值?

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不是此处的通用/转发参考。我知道这个函数最有可能更有用,如果它实际上是,但好奇都是一样的。

c++ c++11 move-semantics perfect-forwarding
3个回答
1
投票

要了解这种情况,您必须了解转发引用的工作原理。给定一个定义

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

当你写的东西像

some_type some_object;
foo(some_object);

模板演绎推论Tsome_type&。现在参数t的类型为some_type& &&。由于您不能引用引用,因此应用reference collapsing规则并将some_type& &&折叠为some_type&

相反,如果你写了类似的东西

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

模板演绎推论Tsome_type。现在参数t的类型为some_type&&。这是一个完全有效的类型,因此没有参考折叠。

现在我们到达std::forward。所有std::forward<U>都将其参数投射到U&&。如果Usome_type,如上面第二种情况那样,参数将被强制转换为some_type&&。它仍然是一个右值参考。如果Usome_type&,就像上面的第一个案例那样,再次执行参考折叠,并且some_type& &&变成some_type&。所以std::forward返回一个左值引用。

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


2
投票

std::forward相当于std::forward<T>(c)

如果static_cast<T&&>(c)是转发引用,那么这允许左值作为左值转发,因为T&&将被推导为左值引用类型,并且T将是引用 - 折叠规则的相同左值引用类型。在您的情况下,T&&不是转发参考,所以这不起作用。


1
投票

好吧,T&&的定义是将std::forward<T>(x)转换为x类型。如果你传递一个非参考作为参数,你将获得一个右值参考T&&。由于您的T&&不能是引用类型(您不能引用引用),因此它必须是非引用类型。

© www.soinside.com 2019 - 2024. All rights reserved.