Convert std::tuple to std::array C++11 Convert std::tuple to std::array C++11 arrays arrays

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).