【发布时间】:2014-06-06 13:22:23
【问题描述】:
考虑以下代码:
class Widget{};
template<typename T>
T &&foo2(T &&t){
return std::forward<T>( t );
}
/// Return 1st element
template<typename T>
typename std::tuple_element<0, typename std::decay<T>::type >::type &&foo(T &&t){
return std::forward< typename std::tuple_element<0, typename std::decay<T>::type >::type >
( std::get<0>(t) );
}
Widget w;
auto list = std::make_tuple(
w,
Widget()
);
int main()
{
auto &l = foo(list ); // This is NOT work
//auto &l2 = foo2( std::get<0>(list) ); // This one works.
}
http://coliru.stacked-crooked.com/a/4d3b74ca6f043e45
当我试图编译这个时,我得到了以下错误:
error: invalid initialization of non-const reference of type 'Widget&' from an rvalue of type 'std::tuple_element<0ul, std::tuple<Widget, Widget> >::type {aka Widget}'
嗯,没关系,但是:
起初,Widget w 不是临时的。为什么它把它当作临时的?
其次,为什么 foo2 比 foo2 更有效?
附:如您所见,我尝试编写同时使用左值和右值操作的函数。如果第一个元素是临时的,我想返回右值,如果不是 - 左值。
【问题讨论】:
-
你知道
std::make_tuple(w, Widget())的类型是std::tuple<Widget, Widget>而不是std::tuple<Widget&, Widget&&>吗?如果你想推导出一个引用类型的元组,你需要std::forward_as_tuple(w, Widget()),它将返回std::tuple<Widget&, Widget&&>。或者这里真正的问题是你想要一个函数来创建一个元组,该元组具有一个用于左值引用输入的左值引用和一个用于右值引用输入的普通值? -
我需要一个同时接受 forward_as_tuple 和 make_tuple 的函数。并在第一种情况下返回右值引用,在第二种情况下返回左值引用(返回值是元组元素之一)。
标签: c++ templates c++11 rvalue-reference