通过引入std::apply()
,这是非常简单的:
template <class Tuple,
class T = std::decay_t<std::tuple_element_t<0, std::decay_t<Tuple>>>>
std::vector<T> to_vector(Tuple&& tuple)
{
return std::apply([](auto&&... elems){
return std::vector<T>{std::forward<decltype(elems)>(elems)...};
}, std::forward<Tuple>(tuple));
}
std::apply()
是一个C++ 17的功能,但在C +可实现+14(请参阅可能的实施链接)。作为一种改进,您可以添加SFINAE或static_assert
,Tuple中的所有类型实际上都是T
。
T.C.作为分出来,这招致每一元件的额外拷贝,因为std::initializer_list
由const
阵列的支持。那真不幸。我们赢得了一些不必对每个元素进行边界检查,但在复制上失去一些。复制结束是太贵了,一个替代的实现是:
template <class Tuple,
class T = std::decay_t<std::tuple_element_t<0, std::decay_t<Tuple>>>>
std::vector<T> to_vector(Tuple&& tuple)
{
return std::apply([](auto&&... elems) {
using expander = int[];
std::vector<T> result;
result.reserve(sizeof...(elems));
expander{(void(
result.push_back(std::forward<decltype(elems)>(elems))
), 0)...};
return result;
}, std::forward<Tuple>(tuple));
}
的扩张招的说明,请参见this answer。请注意,由于我们知道该包不是空的,因此我放弃了领先的0
。用C++ 17,这变得与折叠表达清洁器:
return std::apply([](auto&&... elems) {
std::vector<T> result;
result.reserve(sizeof...(elems));
(result.push_back(std::forward<decltype(elems)>(elems)), ...);
return result;
}, std::forward<Tuple>(tuple));
虽然仍相对不一样好的initializer_list
构造函数。不幸的。
[迭代过元组]的可能的复制(http://stackoverflow.com/questions/1198260/iterate-over-tuple) – filmor
完全不同。更好地与[索引技巧](http://loungecpp.wikidot.com/tips-and-tricks:indices)接触。 – Xeo