fork(1) download
  1. #include <iostream>
  2. #include <type_traits>
  3. #include <array>
  4. #include <utility>
  5. #include <tuple>
  6.  
  7. //get_size
  8. template <typename T_head>
  9. constexpr size_t get_size()
  10. {
  11. return sizeof(T_head);
  12. }
  13.  
  14. template <typename T_head, typename T_second, typename... T_tail>
  15. constexpr size_t get_size()
  16. {
  17. return get_size<T_head>() + get_size<T_second, T_tail...>();
  18. }
  19.  
  20.  
  21. //concat
  22. template<size_t N1, size_t... I1, size_t N2, size_t... I2>
  23. constexpr std::array<size_t, N1+N2> concat(const std::array<size_t, N1>& a1, const std::array<size_t, N2>& a2, std::index_sequence<I1...>, std::index_sequence<I2...>)
  24. {
  25. return { a1[I1]..., a2[I2]... };
  26. }
  27.  
  28. template<size_t N1, size_t N2>
  29. constexpr std::array<size_t, N1+N2> concat(const std::array<size_t, N1>& a1, const std::array<size_t, N2>& a2)
  30. {
  31. return concat(a1, a2, std::make_index_sequence<N1>{}, std::make_index_sequence<N2>{});
  32. }
  33.  
  34.  
  35. //make_index_array
  36. template<size_t T_offset, typename T_head>
  37. constexpr std::array<size_t, 1> make_index_array()
  38. {
  39. return {T_offset};
  40. }
  41.  
  42. template<size_t T_offset, typename T_head, typename T_Second, typename... T_tail>
  43. constexpr std::array<size_t, (sizeof...(T_tail) + 2)> make_index_array()
  44. {
  45. return concat(
  46. make_index_array<T_offset, T_head>(),
  47. make_index_array<T_offset + sizeof(T_head),T_Second, T_tail...>()
  48. );
  49. }
  50.  
  51. template<typename... T_args>
  52. constexpr std::array<size_t, (sizeof...(T_args))> make_index_array()
  53. {
  54. return make_index_array<0, T_args...>();
  55. }
  56.  
  57.  
  58. template<int N, typename... Ts>
  59. using T_param = typename std::tuple_element<N, std::tuple<Ts...>>::type;
  60.  
  61.  
  62. template <typename... T_args>
  63. struct standard_layout_tuple
  64. {
  65. static constexpr std::array<size_t, sizeof...(T_args)> index_array = make_index_array<T_args...>();
  66.  
  67. char storage[get_size<T_args...>()];
  68.  
  69. //Initialization
  70. template<size_t T_index, typename T_val>
  71. void initialize(T_val&& val)
  72. {
  73. void* place = &this->storage[index_array[T_index]];
  74. new(place) T_val(std::forward<T_val>(val));
  75. }
  76.  
  77. template<size_t T_index, typename T_val, typename T_val2, typename... T_vals_rest>
  78. void initialize(T_val&& val, T_val2&& val2, T_vals_rest&&... vals_rest)
  79. {
  80. initialize<T_index, T_val>(std::forward<T_val>(val));
  81. initialize<T_index+1, T_val2, T_vals_rest...>(std::forward<T_val2>(val2), std::forward<T_vals_rest>(vals_rest)...);
  82. }
  83.  
  84. void initialize(T_args&&... args)
  85. {
  86. initialize<0, T_args...>(std::forward<T_args>(args)...);
  87. }
  88.  
  89. standard_layout_tuple(T_args&&... args)
  90. {
  91. initialize(std::forward<T_args>(args)...);
  92. }
  93.  
  94. //Destruction
  95. template<size_t T_index, typename T_val>
  96. void destroy()
  97. {
  98. T_val* place = reinterpret_cast<T_val*>(&this->storage[index_array[T_index]]);
  99. place->~T_val();
  100. }
  101.  
  102. template<size_t T_index, typename T_val, typename T_val2, typename... T_vals_rest>
  103. void destroy()
  104. {
  105. destroy<T_index, T_val>();
  106. destroy<T_index+1, T_val2, T_vals_rest...>();
  107. }
  108.  
  109. void destroy()
  110. {
  111. destroy<0, T_args...>();
  112. }
  113.  
  114. ~standard_layout_tuple()
  115. {
  116. destroy();
  117. }
  118.  
  119. template<size_t T_index>
  120. void set(T_param<T_index, T_args...>&& data)
  121. {
  122. T_param<T_index, T_args...>* ptr = reinterpret_cast<T_param<T_index, T_args...>*>(&this->storage[index_array[T_index]]);
  123. *ptr = std::forward<T_param<T_index, T_args...>>(data);
  124. }
  125.  
  126. template<size_t T_index>
  127. T_param<T_index, T_args...>& get()
  128. {
  129. return *reinterpret_cast<T_param<T_index, T_args...>*>(&this->storage[index_array[T_index]]);
  130. }
  131. };
  132.  
  133.  
  134. int main() {
  135. standard_layout_tuple<float, double, int, double> sltuple{5.5f, 3.4, 7, 1.22};
  136. sltuple.set<2>(47);
  137.  
  138. std::cout << sltuple.get<0>() << std::endl;
  139. std::cout << sltuple.get<1>() << std::endl;
  140. std::cout << sltuple.get<2>() << std::endl;
  141. std::cout << sltuple.get<3>() << std::endl;
  142.  
  143. std::cout << "is standard layout:" << std::endl;
  144. std::cout << std::boolalpha << std::is_standard_layout<standard_layout_tuple<float, double, int, double>>::value << std::endl;
  145.  
  146. return 0;
  147. }
Success #stdin #stdout 0s 3412KB
stdin
Standard input is empty
stdout
5.5
3.4
47
1.22
is standard layout:
true