You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

159 line
5.2 KiB

  1. #pragma once
  2. #include <utility>
  3. #include <cpputils/mp/core/modifier.h>
  4. #include <cpputils/mp/core/conditionals.h>
  5. #include <cpputils/mp/misc/make.h>
  6. #include <cpputils/mp/misc/tag_of.h>
  7. #include <cpputils/mp/intern/ebo.h>
  8. #include <cpputils/mp/operations/at.h>
  9. #include <cpputils/mp/operations/unpack.h>
  10. #include <cpputils/mp/operations/transform.h>
  11. namespace utl {
  12. namespace mp {
  13. struct tag_basic_tuple { };
  14. namespace __impl
  15. {
  16. template<size_t>
  17. struct basic_tuple_index;
  18. template<typename Indices, typename... Xn>
  19. struct basic_tuple_impl;
  20. struct basic_tuple_from_other { };
  21. template<size_t... N, typename... Xn>
  22. struct basic_tuple_impl<std::index_sequence<N...>, Xn...>
  23. : intern::ebo<basic_tuple_index<N>, Xn>...
  24. {
  25. static constexpr size_t _size = sizeof...(Xn);
  26. constexpr basic_tuple_impl() = default;
  27. template<typename Other>
  28. explicit constexpr basic_tuple_impl(basic_tuple_from_other, Other&& other)
  29. : intern::ebo<basic_tuple_index<N>, Xn>(intern::ebo_get<basic_tuple_index<N>>(std::forward<Other>(other)))...
  30. { }
  31. template<typename... Yn>
  32. explicit constexpr basic_tuple_impl(Yn&&... yn)
  33. : intern::ebo<basic_tuple_index<N>, Xn>(std::forward<Yn>(yn))...
  34. { }
  35. };
  36. }
  37. template<typename... Xn>
  38. struct basic_tuple final
  39. : __impl::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...>
  40. {
  41. using tag = tag_basic_tuple;
  42. using base_type = __impl::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...>;
  43. constexpr basic_tuple() = default;
  44. template<typename Other, typename = enable_if<is_same<basic_tuple, decay_type<Other>>>>
  45. constexpr basic_tuple(Other&& other)
  46. : base_type(__impl::basic_tuple_from_other { }, std::forward<Other>(other))
  47. { }
  48. template<typename... Yn>
  49. explicit constexpr basic_tuple(Yn&&... yn)
  50. : base_type(std::forward<Yn>(yn)...)
  51. { }
  52. template<typename N>
  53. constexpr auto at(const N& n) const
  54. { return mp::at(*this, n); }
  55. template<typename F>
  56. constexpr auto unpack(F&& f) const
  57. { return mp::unpack(*this, std::forward<F>(f)); }
  58. template<typename F>
  59. constexpr auto transform(F&& f) const
  60. { return mp::transform(*this, std::forward<F>(f)); }
  61. };
  62. constexpr auto make_basic_tuple = make<tag_basic_tuple>;
  63. namespace __impl
  64. {
  65. /* tag_of */
  66. template<typename... Xn>
  67. struct tag_of_impl<basic_tuple<Xn...>>
  68. { using type = tag_basic_tuple; };
  69. /* make */
  70. template<>
  71. struct make_impl<tag_basic_tuple>
  72. {
  73. template<typename... Xn>
  74. static constexpr auto apply(Xn&&... xn)
  75. { return basic_tuple<decay_type<Xn>...> { std::forward<Xn>(xn)... }; }
  76. };
  77. /* unpack */
  78. template<>
  79. struct unpack_impl<tag_basic_tuple>
  80. {
  81. template<size_t... I, typename... Xn, typename F>
  82. static constexpr auto apply(const basic_tuple_impl<std::index_sequence<I...>, Xn...>& xs, F&& f)
  83. {
  84. return std::forward<F>(f)(
  85. intern::ebo_get<basic_tuple_index<I>>(
  86. static_cast<const intern::ebo<basic_tuple_index<I>, Xn>&>(xs)
  87. )...
  88. );
  89. }
  90. template<size_t... I, typename... Xn, typename F>
  91. static constexpr auto apply(basic_tuple_impl<std::index_sequence<I...>, Xn...>& xs, F&& f)
  92. {
  93. return std::forward<F>(f)(
  94. intern::ebo_get<basic_tuple_index<I>>(
  95. static_cast<intern::ebo<basic_tuple_index<I>, Xn>&>(xs)
  96. )...
  97. );
  98. }
  99. template<size_t... I, typename... Xn, typename F>
  100. static constexpr auto apply(basic_tuple_impl<std::index_sequence<I...>, Xn...>&& xs, F&& f)
  101. {
  102. return std::forward<F>(f)(
  103. intern::ebo_get<basic_tuple_index<I>>(
  104. static_cast<intern::ebo<basic_tuple_index<I>, Xn>&&>(xs)
  105. )...
  106. );
  107. }
  108. };
  109. /* at */
  110. template<>
  111. struct at_impl<tag_basic_tuple>
  112. {
  113. template<typename Xs, typename N>
  114. static constexpr auto apply(Xs&& xs, const N&)
  115. {
  116. constexpr size_t index = N::value;
  117. return intern::ebo_get<basic_tuple_index<index>>(std::forward<Xs>(xs));
  118. }
  119. };
  120. }
  121. template <size_t N, typename... Xn>
  122. constexpr auto at_c(const basic_tuple<Xn...>& x)
  123. { return intern::ebo_get<__impl::basic_tuple_index<N>>(x); }
  124. template <size_t N, typename... Xn>
  125. constexpr auto at_c(basic_tuple<Xn...>& x)
  126. { return intern::ebo_get<__impl::basic_tuple_index<N>>(x); }
  127. template <size_t N, typename... Xn>
  128. constexpr auto at_c(basic_tuple<Xn...>&& x)
  129. { return intern::ebo_get<__impl::basic_tuple_index<N>>(std::forward<basic_tuple<Xn...>>(x)); }
  130. }
  131. }