#include #include #include #include template constexpr std::array to_array_detail(T* data, std::index_sequence) { return std::array{data[Idx]...}; } template constexpr std::array to_array(T* data) { std::make_index_sequence indices; return to_array_detail(data, indices); } template constexpr size_t total_length() { return (std::tuple_size>::value + ...); // neat new "fold expressions" (N4295) available from clang trunk + std=c++1z } template constexpr auto inner_outer() { constexpr size_t nbEl = total_length(); constexpr size_t nbTup = sizeof...(Tuples); size_t tupSizes[nbTup] = {std::tuple_size>::value...}; size_t inner[nbEl] = {0}; size_t outer[nbEl] = {0}; int index = 0; for(int i = 0 ; i < nbTup; i++) { for(int j = 0; j < tupSizes[i]; j++, index++) { inner[index] = i; outer[index] = j; } } // annoying workaround for the lack of constexpr std::array operator[]. // We are forced to work with plain C array before converting them to std::array std::array in = to_array(inner); std::array out = to_array(outer); return std::make_pair(in, out); } template auto tuple_cat_detail2(std::index_sequence, std::index_sequence, Tuples ts) { return std::make_tuple(std::get(std::get(ts))...); } template auto tuple_cat_detail(std::index_sequence, Tuples&&... ts) { constexpr auto in_out = inner_outer(); // pair of inner and outer array of indices return tuple_cat_detail2(std::index_sequence(), std::index_sequence(), std::forward_as_tuple(std::forward(ts)...)); } template auto my_tuple_cat(Tuples&&... ts) { constexpr size_t totalLength = total_length(); return tuple_cat_detail(std::make_index_sequence(), std::forward(ts)...); } int main() { std::array ta; ta[0] = 1; using T1 = std::tuple; T1 t1{0, 1, 2}; using T2 = std::tuple<>; T2 t2; using T3 = std::tuple; T3 t3{3.0, 4.0, 5.0}; using T4 = std::tuple; T4 t4{nullptr, "hello world"}; std::tuple t = my_tuple_cat(t1, t2, t3, t4); std::cout << std::get<0>(t) << "\n"; std::cout << std::get<1>(t) << "\n"; std::cout << std::get<2>(t) << "\n"; std::cout << std::get<3>(t) << "\n"; std::cout << std::get<4>(t) << "\n"; std::cout << std::get<5>(t) << "\n"; std::cout << std::get<6>(t) << "\n"; std::cout << std::get<7>(t) << "\n"; }