、これは非常に簡単です:
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
のいずれかを追加して、タプルのすべてのタイプが実際に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
を削除しました。
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
コンストラクタとしてまだ比較的ように素敵ではないが:C++ 17で、これは折り畳み式できれいになります。残念です。
[繰り返しのタプル]の可能な複製(http://stackoverflow.com/questions/1198260/iterate-over-tuple) – filmor
完全に異なる。 [indices trick](http://loungecpp.wikidot.com/tips-and-tricks:indices)でより良いアプローチが得られました。 – Xeo