【发布时间】:2018-06-02 23:20:06
【问题描述】:
以下代码:
#include <tuple>
int main ()
{
auto f = [] () -> decltype (auto)
{
return std::get<0> (std::make_tuple (0));
};
return f ();
}
(静默)生成具有未定义行为的代码 - make_tuple 返回的临时右值通过 std::get 和 decltype(auto) 传播到返回类型。因此,它最终返回对超出范围的临时对象的引用。在这里查看https://godbolt.org/g/X1UhSw。
现在,您可能会争辩说我对decltype(auto) 的使用是错误的。但是在我的通用代码中(元组的类型可能是std::tuple<Foo &>)我不想总是复制。我真的很想从元组中提取确切的值或引用。
我的感觉是std::get 的这种过载很危险:
template< std::size_t I, class... Types >
constexpr std::tuple_element_t<I, tuple<Types...> >&&
get( tuple<Types...>&& t ) noexcept;
虽然将左值引用传播到元组元素上可能是明智的,但我认为右值引用并不适用。
我确信标准委员会对此进行了非常仔细的考虑,但谁能向我解释为什么这被认为是最佳选择?
【问题讨论】:
-
“我认为这不适用于右值引用” - 如果你
forward_as_tuple就可以。您希望保留值类别。或者,如果您想从函数返回值中提取一个值。 -
谢谢,但我不确定它是否保留了价值类别。例如,如果我有一个返回
std::tuple<int>的函数并且我在其上调用std::get<0>,我希望得到一个普通的int,而不是int&&。你能给我一个具体的例子吗? -
这种
get的重载不是有效的结构化绑定所必需的吗? -
我当然愿意被说服,但是我尝试过使用“安全”版本的重载(在传递右值引用元组时只返回朴素的
tuple_element类型)的示例似乎工作正常。我错过了什么?
标签: c++ c++11 c++14 rvalue-reference stdtuple