Search code examples
c++arraysc++11tuplesstdarray

How do you convert a homogeneous std::tuple to a std::array?


If I have std::tuple<double, double, double, ...> (where the types are homogeneous), is there a stock function or constructor to convert to std::array<double, N>?

I was able to get it working with recursive template code (my draft answer posted below), but I would prefer someone else's, hopefully better solution.


Solution

  • 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>
    constexpr
    typename build_indices<std::tuple_size<Bare<Tuple>>::value>::type
    make_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;
    }