要求朋友:
为什么以下代码中的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
不是通用/转发参考。我知道这个函数最有可能更有用,如果它实际上是,但好奇都一样。
答案 0 :(得分:2)
std::forward<T>(c)
相当于static_cast<T&&>(c)
。
如果T&&
是转发引用,则允许左值作为左值转发,因为T
将被推导为左值引用类型,T&&
将是相同的左值引用按引用 - 折叠规则键入。在您的情况下,T&&
不是转发引用,因此这不起作用。
答案 1 :(得分:1)
嗯,std::forward<T>(x)
的定义是将x
转换为T&&
类型。如果你传递一个非参考作为参数,你将得到一个右值引用T&&
。由于您的T
不能是引用类型(您不能引用引用),因此它必须是非引用类型。
答案 2 :(得分:1)
要了解这种情况,您必须了解转发引用的工作原理。给出像
这样的定义template <typename T>
void foo(T&& t) {}
当你写
之类的东西时some_type some_object;
foo(some_object);
模板推导会将T
推断为some_type&
。现在,参数t
的类型为some_type& &&
。由于您无法引用引用,因此会应用reference collapsing规则并将some_type& &&
折叠为some_type&
。
相反,如果你写了类似
的内容some_type some_object;
foo(std::move(some_object));
模板推导会将T
推断为some_type
。现在,参数t
的类型为some_type&&
。这是一个完全有效的类型,因此没有参考折叠。
现在我们到达std::forward
。所有std::forward<U>
都将其参数强制转换为U&&
。如果U
为some_type
,则与上面的第二种情况一样,参数将转换为some_type&&
。它仍然是一个右值参考。如果U
为some_type&
,与上述第一种情况相同,则会再次执行参考折叠,some_type& &&
变为some_type&
。因此std::forward
会返回左值引用。
因此,对原始问题的最终答案是std::forward
的返回类型仅取决于作为std::forward
模板参数传递的类型。由于您的案例中的T
将始终推断为非引用类型,因此std::forward
将始终返回rvalue-reference。