basic_tuple.hpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /*!
  2. @file
  3. Defines `boost::hana::basic_tuple`.
  4. Copyright Louis Dionne 2013-2022
  5. Distributed under the Boost Software License, Version 1.0.
  6. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  7. */
  8. #ifndef BOOST_HANA_BASIC_TUPLE_HPP
  9. #define BOOST_HANA_BASIC_TUPLE_HPP
  10. #include <boost/hana/fwd/basic_tuple.hpp>
  11. #include <boost/hana/config.hpp>
  12. #include <boost/hana/detail/decay.hpp>
  13. #include <boost/hana/detail/ebo.hpp>
  14. #include <boost/hana/fwd/at.hpp>
  15. #include <boost/hana/fwd/bool.hpp>
  16. #include <boost/hana/fwd/concept/sequence.hpp>
  17. #include <boost/hana/fwd/core/make.hpp>
  18. #include <boost/hana/fwd/core/tag_of.hpp>
  19. #include <boost/hana/fwd/drop_front.hpp>
  20. #include <boost/hana/fwd/integral_constant.hpp>
  21. #include <boost/hana/fwd/is_empty.hpp>
  22. #include <boost/hana/fwd/length.hpp>
  23. #include <boost/hana/fwd/transform.hpp>
  24. #include <boost/hana/fwd/unpack.hpp>
  25. #include <cstddef>
  26. #include <type_traits>
  27. #include <utility>
  28. namespace boost { namespace hana {
  29. namespace detail {
  30. //////////////////////////////////////////////////////////////////////
  31. // basic_tuple_impl<n, Xn>
  32. //////////////////////////////////////////////////////////////////////
  33. template <std::size_t> struct bti; // basic_tuple_index
  34. struct from_other { };
  35. template <typename Indices, typename ...Xn>
  36. #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
  37. struct __declspec(empty_bases) basic_tuple_impl;
  38. #else
  39. struct basic_tuple_impl;
  40. #endif
  41. template <std::size_t ...n, typename ...Xn>
  42. #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
  43. struct __declspec(empty_bases) basic_tuple_impl<std::index_sequence<n...>, Xn...>
  44. #else
  45. struct basic_tuple_impl<std::index_sequence<n...>, Xn...>
  46. #endif
  47. : detail::ebo<bti<n>, Xn>...
  48. {
  49. static constexpr std::size_t size_ = sizeof...(Xn);
  50. constexpr basic_tuple_impl() = default;
  51. template <typename Other>
  52. explicit constexpr basic_tuple_impl(detail::from_other, Other&& other)
  53. : detail::ebo<bti<n>, Xn>(detail::ebo_get<bti<n>>(static_cast<Other&&>(other)))...
  54. { }
  55. template <typename ...Yn>
  56. explicit constexpr basic_tuple_impl(Yn&& ...yn)
  57. : detail::ebo<bti<n>, Xn>(static_cast<Yn&&>(yn))...
  58. { }
  59. };
  60. }
  61. //////////////////////////////////////////////////////////////////////////
  62. // basic_tuple
  63. //////////////////////////////////////////////////////////////////////////
  64. //! @cond
  65. template <typename ...Xn>
  66. struct basic_tuple final
  67. : detail::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...>
  68. {
  69. using Base = detail::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...>;
  70. constexpr basic_tuple() = default;
  71. // copy constructor
  72. template <typename Other, typename = typename std::enable_if<
  73. std::is_same<typename detail::decay<Other>::type, basic_tuple>::value
  74. >::type>
  75. constexpr basic_tuple(Other&& other)
  76. : Base(detail::from_other{}, static_cast<Other&&>(other))
  77. { }
  78. template <typename ...Yn>
  79. explicit constexpr basic_tuple(Yn&& ...yn)
  80. : Base(static_cast<Yn&&>(yn)...)
  81. { }
  82. };
  83. //! @endcond
  84. template <typename ...Xn>
  85. struct tag_of<basic_tuple<Xn...>> {
  86. using type = basic_tuple_tag;
  87. };
  88. //////////////////////////////////////////////////////////////////////////
  89. // Foldable
  90. //////////////////////////////////////////////////////////////////////////
  91. template <>
  92. struct unpack_impl<basic_tuple_tag> {
  93. template <std::size_t ...i, typename ...Xn, typename F>
  94. static constexpr decltype(auto)
  95. apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F&& f) {
  96. return static_cast<F&&>(f)(
  97. detail::ebo_get<detail::bti<i>>(
  98. static_cast<detail::ebo<detail::bti<i>, Xn> const&>(xs)
  99. )...
  100. );
  101. }
  102. template <std::size_t ...i, typename ...Xn, typename F>
  103. static constexpr decltype(auto)
  104. apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F&& f) {
  105. return static_cast<F&&>(f)(
  106. detail::ebo_get<detail::bti<i>>(
  107. static_cast<detail::ebo<detail::bti<i>, Xn>&>(xs)
  108. )...
  109. );
  110. }
  111. template <std::size_t ...i, typename ...Xn, typename F>
  112. static constexpr decltype(auto)
  113. apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F&& f) {
  114. return static_cast<F&&>(f)(
  115. detail::ebo_get<detail::bti<i>>(
  116. static_cast<detail::ebo<detail::bti<i>, Xn>&&>(xs)
  117. )...
  118. );
  119. }
  120. };
  121. //////////////////////////////////////////////////////////////////////////
  122. // Functor
  123. //////////////////////////////////////////////////////////////////////////
  124. template <>
  125. struct transform_impl<basic_tuple_tag> {
  126. template <std::size_t ...i, typename ...Xn, typename F>
  127. static constexpr auto
  128. apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F const& f) {
  129. return hana::make_basic_tuple(
  130. f(detail::ebo_get<detail::bti<i>>(
  131. static_cast<detail::ebo<detail::bti<i>, Xn> const&>(xs)
  132. ))...
  133. );
  134. }
  135. template <std::size_t ...i, typename ...Xn, typename F>
  136. static constexpr auto
  137. apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F const& f) {
  138. return hana::make_basic_tuple(
  139. f(detail::ebo_get<detail::bti<i>>(
  140. static_cast<detail::ebo<detail::bti<i>, Xn>&>(xs)
  141. ))...
  142. );
  143. }
  144. template <std::size_t ...i, typename ...Xn, typename F>
  145. static constexpr auto
  146. apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F const& f) {
  147. return hana::make_basic_tuple(
  148. f(detail::ebo_get<detail::bti<i>>(
  149. static_cast<detail::ebo<detail::bti<i>, Xn>&&>(xs)
  150. ))...
  151. );
  152. }
  153. };
  154. //////////////////////////////////////////////////////////////////////////
  155. // Iterable
  156. //////////////////////////////////////////////////////////////////////////
  157. template <>
  158. struct at_impl<basic_tuple_tag> {
  159. template <typename Xs, typename N>
  160. static constexpr decltype(auto) apply(Xs&& xs, N const&) {
  161. constexpr std::size_t index = N::value;
  162. return detail::ebo_get<detail::bti<index>>(static_cast<Xs&&>(xs));
  163. }
  164. };
  165. template <>
  166. struct drop_front_impl<basic_tuple_tag> {
  167. template <std::size_t N, typename Xs, std::size_t ...i>
  168. static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
  169. return hana::make_basic_tuple(
  170. detail::ebo_get<detail::bti<i+N>>(static_cast<Xs&&>(xs))...
  171. );
  172. }
  173. template <typename Xs, typename N>
  174. static constexpr auto apply(Xs&& xs, N const&) {
  175. constexpr std::size_t len = detail::decay<Xs>::type::size_;
  176. return drop_front_helper<N::value>(static_cast<Xs&&>(xs), std::make_index_sequence<
  177. (N::value < len) ? len - N::value : 0
  178. >{});
  179. }
  180. };
  181. template <>
  182. struct is_empty_impl<basic_tuple_tag> {
  183. template <typename ...Xs>
  184. static constexpr hana::bool_<sizeof...(Xs) == 0>
  185. apply(basic_tuple<Xs...> const&)
  186. { return {}; }
  187. };
  188. // compile-time optimizations (to reduce the # of function instantiations)
  189. template <std::size_t n, typename ...Xs>
  190. constexpr decltype(auto) at_c(basic_tuple<Xs...> const& xs) {
  191. return detail::ebo_get<detail::bti<n>>(xs);
  192. }
  193. template <std::size_t n, typename ...Xs>
  194. constexpr decltype(auto) at_c(basic_tuple<Xs...>& xs) {
  195. return detail::ebo_get<detail::bti<n>>(xs);
  196. }
  197. template <std::size_t n, typename ...Xs>
  198. constexpr decltype(auto) at_c(basic_tuple<Xs...>&& xs) {
  199. return detail::ebo_get<detail::bti<n>>(static_cast<basic_tuple<Xs...>&&>(xs));
  200. }
  201. //////////////////////////////////////////////////////////////////////////
  202. // Sequence
  203. //////////////////////////////////////////////////////////////////////////
  204. template <>
  205. struct Sequence<basic_tuple_tag> {
  206. static constexpr bool value = true;
  207. };
  208. template <>
  209. struct make_impl<basic_tuple_tag> {
  210. template <typename ...Xn>
  211. static constexpr basic_tuple<typename detail::decay<Xn>::type...>
  212. apply(Xn&& ...xn) {
  213. return basic_tuple<typename detail::decay<Xn>::type...>{
  214. static_cast<Xn&&>(xn)...
  215. };
  216. }
  217. };
  218. //////////////////////////////////////////////////////////////////////////
  219. // length
  220. //////////////////////////////////////////////////////////////////////////
  221. template <>
  222. struct length_impl<basic_tuple_tag> {
  223. template <typename ...Xn>
  224. static constexpr auto apply(basic_tuple<Xn...> const&) {
  225. return hana::size_t<sizeof...(Xn)>{};
  226. }
  227. };
  228. }} // end namespace boost::hana
  229. #endif // !BOOST_HANA_BASIC_TUPLE_HPP