SHARE
TWEET

tuple_cat constepxr style

a guest Nov 16th, 2014 327 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <tuple>
  2. #include <iostream>
  3. #include <string>
  4. #include <array>
  5.  
  6.  
  7. template <typename T, size_t N, size_t... Idx>
  8. constexpr std::array<T, N> to_array_detail(T* data, std::index_sequence<Idx...>)
  9. {
  10.    return std::array<T, N>{data[Idx]...};
  11. }
  12.  
  13. template <typename T, size_t N>
  14. constexpr std::array<T, N> to_array(T* data)
  15. {
  16.    std::make_index_sequence<N> indices;
  17.    return to_array_detail<T, N>(data, indices);
  18. }
  19.  
  20. template <typename... Tuples>
  21. constexpr size_t total_length()
  22. {
  23.    return (std::tuple_size<std::decay_t<Tuples>>::value + ...); // neat new "fold expressions" (N4295) available from clang trunk + std=c++1z
  24. }
  25.  
  26.  
  27. template <typename... Tuples>
  28. constexpr auto inner_outer()
  29. {
  30.     constexpr size_t nbEl = total_length<Tuples...>();
  31.     constexpr size_t nbTup = sizeof...(Tuples);
  32.     size_t tupSizes[nbTup] = {std::tuple_size<std::decay_t<Tuples>>::value...};
  33.     size_t inner[nbEl] = {0};
  34.     size_t outer[nbEl] = {0};
  35.  
  36.     int index = 0;
  37.     for(int i = 0 ; i < nbTup; i++)
  38.     {
  39.        for(int j = 0; j < tupSizes[i]; j++, index++)
  40.        {
  41.           inner[index] = i;
  42.           outer[index] = j;
  43.        }
  44.     }
  45.  
  46.     // annoying workaround for the lack of constexpr std::array operator[].
  47.     // We are forced to work with plain C array before converting them to std::array
  48.     std::array<size_t, nbEl> in = to_array<size_t, nbEl>(inner);
  49.     std::array<size_t, nbEl> out = to_array<size_t, nbEl>(outer);
  50.  
  51.     return std::make_pair(in, out);
  52. }
  53.  
  54. template <size_t... inner, size_t... outer, typename Tuples>
  55. auto tuple_cat_detail2(std::index_sequence<inner...>, std::index_sequence<outer...>, Tuples ts)
  56. {
  57.    return std::make_tuple(std::get<outer>(std::get<inner>(ts))...);
  58. }
  59.  
  60. template <typename... Tuples, size_t... Idx>
  61. auto tuple_cat_detail(std::index_sequence<Idx...>, Tuples&&... ts)
  62. {
  63.    constexpr auto in_out = inner_outer<Tuples...>(); // pair of inner and outer array of indices
  64.    return tuple_cat_detail2(std::index_sequence<in_out.first[Idx]...>(),
  65.                             std::index_sequence<in_out.second[Idx]...>(),
  66.                             std::forward_as_tuple(std::forward<Tuples>(ts)...));
  67. }
  68.  
  69. template <typename... Tuples>
  70. auto my_tuple_cat(Tuples&&... ts)
  71. {
  72.  
  73.    constexpr size_t totalLength = total_length<Tuples...>();
  74.    return tuple_cat_detail(std::make_index_sequence<totalLength>(), std::forward<Tuples>(ts)...);
  75. }
  76.  
  77. int main()
  78. {
  79.   std::array<int, 5> ta;
  80.   ta[0] = 1;
  81.   using T1 = std::tuple<int, short, long>; T1 t1{0, 1, 2};
  82.   using T2 = std::tuple<>; T2 t2;
  83.   using T3 = std::tuple<float, double, long double>; T3 t3{3.0, 4.0, 5.0};
  84.   using T4 = std::tuple<void*, const char*>; T4 t4{nullptr, "hello world"};
  85.  
  86.   std::tuple<int, short, long, float, double, long double, void*, const char*> t = my_tuple_cat(t1, t2, t3, t4);
  87.   std::cout << std::get<0>(t) << "\n";
  88.   std::cout << std::get<1>(t) << "\n";
  89.   std::cout << std::get<2>(t) << "\n";
  90.   std::cout << std::get<3>(t) << "\n";
  91.   std::cout << std::get<4>(t) << "\n";
  92.   std::cout << std::get<5>(t) << "\n";
  93.   std::cout << std::get<6>(t) << "\n";
  94.   std::cout << std::get<7>(t) << "\n";
  95. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top