Convert std::tuple to std::array C++11
Converting a tuple to an array without making use of recursion, including use of perfect-forwarding (useful for move-only types):
#include <iostream>#include <tuple>#include <array>template<int... Indices>struct indices { using next = indices<Indices..., sizeof...(Indices)>;};template<int Size>struct build_indices { using type = typename build_indices<Size - 1>::type::next;};template<>struct build_indices<0> { using type = indices<>;};template<typename T>using Bare = typename std::remove_cv<typename std::remove_reference<T>::type>::type;template<typename Tuple>constexprtypename build_indices<std::tuple_size<Bare<Tuple>>::value>::typemake_indices(){ return {}; }template<typename Tuple, int... Indices>std::array< typename std::tuple_element<0, Bare<Tuple>>::type, std::tuple_size<Bare<Tuple>>::value>to_array(Tuple&& tuple, indices<Indices...>){ using std::get; return {{ get<Indices>(std::forward<Tuple>(tuple))... }};}template<typename Tuple>auto to_array(Tuple&& tuple)-> decltype( to_array(std::declval<Tuple>(), make_indices<Tuple>()) ){ return to_array(std::forward<Tuple>(tuple), make_indices<Tuple>());}int main() { std::tuple<double, double, double> tup(1.5, 2.5, 4.5); auto arr = to_array(tup); for (double x : arr) std::cout << x << " "; std::cout << std::endl; return 0;}
The C++17 solution is a short one:
template<typename tuple_t>constexpr auto get_array_from_tuple(tuple_t&& tuple){ constexpr auto get_array = [](auto&& ... x){ return std::array{std::forward<decltype(x)>(x) ... }; }; return std::apply(get_array, std::forward<tuple_t>(tuple));}
Use it as
auto tup = std::make_tuple(1.0,2.0,3.0);auto arr = get_array_from_tuple(tup);
EDIT: forgot to sprinkle constexpr
anywhere :-)
You can do it non-recursively:
#include <array>#include <tuple>#include <redi/index_tuple.h> // see belowtemplate<typename T, typename... U> using Array = std::array<T, 1+sizeof...(U)>;template<typename T, typename... U, unsigned... I> inline Array<T, U...> tuple_to_array2(const std::tuple<T, U...>& t, redi::index_tuple<I...>) { return Array<T, U...>{ std::get<I>(t)... }; }template<typename T, typename... U> inline Array<T, U...> tuple_to_array(const std::tuple<T, U...>& t) { using IndexTuple = typename redi::make_index_tuple<1+sizeof...(U)>::type; return tuple_to_array2(t, IndexTuple()); }
See https://gitlab.com/redistd/redistd/blob/master/include/redi/index_tuple.h for my implementation of index_tuple, something like that is useful for working with tuples and similar variadic templates. A similar utility was standardised as std::index_sequence
in C++14 (see index_seq.h for a standalone C++11 implementation).