如果我有这样的结构:
struct Thing
{
int x;
int y;
bool a;
bool b;
}
然后我可以创建一个 Thing
对象,方法是:Thing t {1,2,true,false};
。但是,如果我有一个元组,那么我会做类似的事情:
std::tuple<int, int, bool, bool> info = std::make_tuple(1,2,true,false);
Thing t { std::get<0>(info), std::get<1>(info).. // and so on
有更好的方法吗?
最佳答案
我们可以创建一个通用工厂函数,用于从类似元组的类型( std::tuple
、 std::pair
、 std::array
和结构化绑定(bind)世界中任意用户定义的类似元组的对象†):
template <class T, class Tuple, size_t... Is>
T construct_from_tuple(Tuple&& tuple, std::index_sequence<Is...> ) {
return T{std::get<Is>(std::forward<Tuple>(tuple))...};
}
template <class T, class Tuple>
T construct_from_tuple(Tuple&& tuple) {
return construct_from_tuple<T>(std::forward<Tuple>(tuple),
std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{}
);
}
在您的情况下将用作:
std::tuple<int, int, bool, bool> info = std::make_tuple(1,2,true,false);
Thing t = construct_from_tuple<Thing>(info); // or std::move(info)
这边,Thing
仍然可以是一个聚合(不必添加构造函数/赋值),我们的解决方案解决了很多很多类型的问题。
作为一项改进,我们可以将 SFINAE 添加到两个重载中,以确保无法使用无效的元组类型调用它们。
†等待接受分解将如何工作的措辞,对 std::get<Is>
的合格调用可能需要更改为对 get<Is>
的不合格调用它有特殊的查找规则。目前,这还没有实际意义,因为现在是 2016 年,我们还没有结构化绑定(bind)。
更新:在 C++17 中,有 std::make_from_tuple()
.
关于c++ - 来自元组的构造函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38440844/