If I have std::tuple<double, double, double>
(where the type is homogeneous), is there a stock function or constructor to convert to std::array<double>
?
Edit:: I was able to get it working with recursive template code (my draft answer posted below). Is this the best way to handle this? It seems like there would be a stock function for this... Or if you have improvements to my answer, I'd appreciate it. I'll leave the question unanswered (after all, I want a good way, not just a workable way), and would prefer to select someone else's [hopefully better] answer.
Thanks for your advice.
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; }
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 :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With