basic_tuple.hpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*!
  2. @file
  3. Defines `boost::hana::basic_tuple`.
  4. @copyright Louis Dionne 2013-2017
  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. BOOST_HANA_NAMESPACE_BEGIN
  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. struct basic_tuple_impl;
  37. template <std::size_t ...n, typename ...Xn>
  38. struct basic_tuple_impl<std::index_sequence<n...>, Xn...>
  39. : detail::ebo<bti<n>, Xn>...
  40. {
  41. static constexpr std::size_t size_ = sizeof...(Xn);
  42. constexpr basic_tuple_impl() = default;
  43. template <typename Other>
  44. explicit constexpr basic_tuple_impl(detail::from_other, Other&& other)
  45. : detail::ebo<bti<n>, Xn>(detail::ebo_get<bti<n>>(static_cast<Other&&>(other)))...
  46. { }
  47. template <typename ...Yn>
  48. explicit constexpr basic_tuple_impl(Yn&& ...yn)
  49. : detail::ebo<bti<n>, Xn>(static_cast<Yn&&>(yn))...
  50. { }
  51. };
  52. }
  53. //////////////////////////////////////////////////////////////////////////
  54. // basic_tuple
  55. //////////////////////////////////////////////////////////////////////////
  56. //! @cond
  57. template <typename ...Xn>
  58. struct basic_tuple final
  59. : detail::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...>
  60. {
  61. using Base = detail::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...>;
  62. constexpr basic_tuple() = default;
  63. // copy constructor
  64. template <typename Other, typename = typename std::enable_if<
  65. std::is_same<typename detail::decay<Other>::type, basic_tuple>::value
  66. >::type>
  67. constexpr basic_tuple(Other&& other)
  68. : Base(detail::from_other{}, static_cast<Other&&>(other))
  69. { }
  70. template <typename ...Yn>
  71. explicit constexpr basic_tuple(Yn&& ...yn)
  72. : Base(static_cast<Yn&&>(yn)...)
  73. { }
  74. };
  75. //! @endcond
  76. template <typename ...Xn>
  77. struct tag_of<basic_tuple<Xn...>> {
  78. using type = basic_tuple_tag;
  79. };
  80. //////////////////////////////////////////////////////////////////////////
  81. // Foldable
  82. //////////////////////////////////////////////////////////////////////////
  83. template <>
  84. struct unpack_impl<basic_tuple_tag> {
  85. template <std::size_t ...i, typename ...Xn, typename F>
  86. static constexpr decltype(auto)
  87. apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F&& f) {
  88. return static_cast<F&&>(f)(
  89. detail::ebo_get<detail::bti<i>>(
  90. static_cast<detail::ebo<detail::bti<i>, Xn> const&>(xs)
  91. )...
  92. );
  93. }
  94. template <std::size_t ...i, typename ...Xn, typename F>
  95. static constexpr decltype(auto)
  96. apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F&& f) {
  97. return static_cast<F&&>(f)(
  98. detail::ebo_get<detail::bti<i>>(
  99. static_cast<detail::ebo<detail::bti<i>, Xn>&>(xs)
  100. )...
  101. );
  102. }
  103. template <std::size_t ...i, typename ...Xn, typename F>
  104. static constexpr decltype(auto)
  105. apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F&& f) {
  106. return static_cast<F&&>(f)(
  107. detail::ebo_get<detail::bti<i>>(
  108. static_cast<detail::ebo<detail::bti<i>, Xn>&&>(xs)
  109. )...
  110. );
  111. }
  112. };
  113. //////////////////////////////////////////////////////////////////////////
  114. // Functor
  115. //////////////////////////////////////////////////////////////////////////
  116. template <>
  117. struct transform_impl<basic_tuple_tag> {
  118. template <std::size_t ...i, typename ...Xn, typename F>
  119. static constexpr auto
  120. apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...> const& xs, F const& f) {
  121. return hana::make_basic_tuple(
  122. f(detail::ebo_get<detail::bti<i>>(
  123. static_cast<detail::ebo<detail::bti<i>, Xn> const&>(xs)
  124. ))...
  125. );
  126. }
  127. template <std::size_t ...i, typename ...Xn, typename F>
  128. static constexpr auto
  129. apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>& xs, F const& f) {
  130. return hana::make_basic_tuple(
  131. f(detail::ebo_get<detail::bti<i>>(
  132. static_cast<detail::ebo<detail::bti<i>, Xn>&>(xs)
  133. ))...
  134. );
  135. }
  136. template <std::size_t ...i, typename ...Xn, typename F>
  137. static constexpr auto
  138. apply(detail::basic_tuple_impl<std::index_sequence<i...>, Xn...>&& xs, F const& f) {
  139. return hana::make_basic_tuple(
  140. f(detail::ebo_get<detail::bti<i>>(
  141. static_cast<detail::ebo<detail::bti<i>, Xn>&&>(xs)
  142. ))...
  143. );
  144. }
  145. };
  146. //////////////////////////////////////////////////////////////////////////
  147. // Iterable
  148. //////////////////////////////////////////////////////////////////////////
  149. template <>
  150. struct at_impl<basic_tuple_tag> {
  151. template <typename Xs, typename N>
  152. static constexpr decltype(auto) apply(Xs&& xs, N const&) {
  153. constexpr std::size_t index = N::value;
  154. return detail::ebo_get<detail::bti<index>>(static_cast<Xs&&>(xs));
  155. }
  156. };
  157. template <>
  158. struct drop_front_impl<basic_tuple_tag> {
  159. template <std::size_t N, typename Xs, std::size_t ...i>
  160. static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
  161. return hana::make_basic_tuple(
  162. detail::ebo_get<detail::bti<i+N>>(static_cast<Xs&&>(xs))...
  163. );
  164. }
  165. template <typename Xs, typename N>
  166. static constexpr auto apply(Xs&& xs, N const&) {
  167. constexpr std::size_t len = detail::decay<Xs>::type::size_;
  168. return drop_front_helper<N::value>(static_cast<Xs&&>(xs), std::make_index_sequence<
  169. N::value < len ? len - N::value : 0
  170. >{});
  171. }
  172. };
  173. template <>
  174. struct is_empty_impl<basic_tuple_tag> {
  175. template <typename ...Xs>
  176. static constexpr hana::bool_<sizeof...(Xs) == 0>
  177. apply(basic_tuple<Xs...> const&)
  178. { return {}; }
  179. };
  180. // compile-time optimizations (to reduce the # of function instantiations)
  181. template <std::size_t n, typename ...Xs>
  182. constexpr decltype(auto) at_c(basic_tuple<Xs...> const& xs) {
  183. return detail::ebo_get<detail::bti<n>>(xs);
  184. }
  185. template <std::size_t n, typename ...Xs>
  186. constexpr decltype(auto) at_c(basic_tuple<Xs...>& xs) {
  187. return detail::ebo_get<detail::bti<n>>(xs);
  188. }
  189. template <std::size_t n, typename ...Xs>
  190. constexpr decltype(auto) at_c(basic_tuple<Xs...>&& xs) {
  191. return detail::ebo_get<detail::bti<n>>(static_cast<basic_tuple<Xs...>&&>(xs));
  192. }
  193. //////////////////////////////////////////////////////////////////////////
  194. // Sequence
  195. //////////////////////////////////////////////////////////////////////////
  196. template <>
  197. struct Sequence<basic_tuple_tag> {
  198. static constexpr bool value = true;
  199. };
  200. template <>
  201. struct make_impl<basic_tuple_tag> {
  202. template <typename ...Xn>
  203. static constexpr basic_tuple<typename detail::decay<Xn>::type...>
  204. apply(Xn&& ...xn) {
  205. return basic_tuple<typename detail::decay<Xn>::type...>{
  206. static_cast<Xn&&>(xn)...
  207. };
  208. }
  209. };
  210. //////////////////////////////////////////////////////////////////////////
  211. // length
  212. //////////////////////////////////////////////////////////////////////////
  213. template <>
  214. struct length_impl<basic_tuple_tag> {
  215. template <typename ...Xn>
  216. static constexpr auto apply(basic_tuple<Xn...> const&) {
  217. return hana::size_t<sizeof...(Xn)>{};
  218. }
  219. };
  220. BOOST_HANA_NAMESPACE_END
  221. #endif // !BOOST_HANA_BASIC_TUPLE_HPP