Vicente J. Botet Escriba wrote:
About the infamous tuple_cat challenge. tuple_cat doesn't append. tuple cat construct a tuple with the elements of its tuple-like parameters...
That's quite true. The tuple_cat implementation in the article is a straightforward reimplementation of Eric's tuple_cat, to illustrate the difference in styles. It fixes one limitation of the original, but others remain. Specifically, it doesn't work when the arguments are const qualified, when the tuple elements are move-only (although this is a defect in std::get), or for tuple-likes apart from std::pair. Fixing those defects one by one: 1. tuple<unique_ptr<int>> can be fixed by replacing template<class R, class...Is, class... Ks, class Tp> R tuple_cat_( mp_list<Is...>, mp_list<Ks...>, Tp tp ) { return R{ std::get<Ks::value>(std::get<Is::value>(tp))... }; } with template<class R, class...Is, class... Ks, class Tp> R tuple_cat_( mp_list<Is...>, mp_list<Ks...>, Tp tp ) { return R{ std::get<Ks::value>(std::get<Is::value>(std::move(tp)))... }; } This shouldn't be necessary though; it's std::get that is broken here. 2. const-qualified tuples: template<class... Tp, class R = mp_append<std::tuple<>, typename std::remove_reference<Tp>::type...>> R tuple_cat( Tp &&... tp ) needs to be replaced with template<class T> using remove_cv_ref = std::remove_cv_t<std::remove_reference_t<T>>; template<class... Tp, class R = mp_append<std::tuple<>, remove_cv_ref<Tp>...>> R tuple_cat( Tp &&... tp ) and the same substitution needs to be done for using list1 = mp_list<mp_rename<typename std::remove_reference<Tp>::type, mp_list>...>; 3. tuple-like types: template<class... Tp, class R = mp_append<std::tuple<>, remove_cv_ref<Tp>...>> R tuple_cat( Tp &&... tp ) needs to be further massaged as follows: template<class N, class T> using element_ = std::tuple_element_t<N::value, T>; template<class T> using from_tuple_like = mp_product<element_, mp_iota<std::tuple_size<T>>, mp_list<T>>; template<class... Tp, class R = mp_append<std::tuple<>, from_tuple_like<remove_cv_ref<Tp>>...>> R tuple_cat( Tp &&... tp ) and similarly for list1: using list1 = mp_list<from_tuple_like<remove_cv_ref<Tp>>...>; With these changes, this now works: { std::array<int, 2> const t1{ 1, 2 }; std::array<float, 3> const t2{ 3.0f, 4.0f, 5.0f }; std::array<std::unique_ptr<int>, 1> t3{ std::unique_ptr<int>{ new int } }; using expected = std::tuple<int, int, float, float, float, std::unique_ptr<int>>; auto result = ::tuple_cat( t1, std::move( t2 ), std::move( t3 ) ); static_assert( std::is_same<decltype(result), expected>::value, "" ); PRINT_TYPE( decltype(result) ); print_tuple( result ); }