vector.hpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. /*!
  2. @file
  3. Adapts `boost::mpl::vector` for use with Hana.
  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_EXT_BOOST_MPL_VECTOR_HPP
  9. #define BOOST_HANA_EXT_BOOST_MPL_VECTOR_HPP
  10. #include <boost/hana/concept/foldable.hpp>
  11. #include <boost/hana/config.hpp>
  12. #include <boost/hana/core/when.hpp>
  13. #include <boost/hana/ext/boost/mpl/integral_c.hpp>
  14. #include <boost/hana/fwd/at.hpp>
  15. #include <boost/hana/fwd/core/to.hpp>
  16. #include <boost/hana/fwd/core/tag_of.hpp>
  17. #include <boost/hana/fwd/drop_front.hpp>
  18. #include <boost/hana/fwd/equal.hpp>
  19. #include <boost/hana/fwd/is_empty.hpp>
  20. #include <boost/hana/fwd/less.hpp>
  21. #include <boost/hana/integral_constant.hpp>
  22. #include <boost/hana/length.hpp>
  23. #include <boost/hana/type.hpp>
  24. #include <boost/hana/unpack.hpp>
  25. #include <boost/mpl/at.hpp>
  26. #include <boost/mpl/empty.hpp>
  27. #include <boost/mpl/equal.hpp>
  28. #include <boost/mpl/sequence_tag.hpp>
  29. #include <boost/mpl/size.hpp>
  30. #include <boost/mpl/vector.hpp>
  31. #include <cstddef>
  32. #include <type_traits>
  33. #include <utility>
  34. #ifdef BOOST_HANA_DOXYGEN_INVOKED
  35. namespace boost { namespace mpl {
  36. //! @ingroup group-ext-mpl
  37. //! Adapter for Boost.MPL vectors.
  38. //!
  39. //!
  40. //! Modeled concepts
  41. //! ----------------
  42. //! It is possible for MPL vectors to model a couple of concepts.
  43. //! However, because they are only able to hold types, they lack
  44. //! the generality required to model concepts like `Functor`,
  45. //! `Sequence` and other related concepts.
  46. //!
  47. //! 1. `Comparable`\n
  48. //! Two MPL vectors are equal if and only if they contain the same
  49. //! number of types, and if all those types are equal.
  50. //! @include example/ext/boost/mpl/vector/comparable.cpp
  51. //!
  52. //! 2. `Foldable`\n
  53. //! Folding a MPL vector is equivalent to folding it as a `Sequence`.
  54. //! @include example/ext/boost/mpl/vector/foldable.cpp
  55. //!
  56. //! 3. `Iterable`\n
  57. //! Iterating over a MPL vector is just iterating over each of the
  58. //! types it contains, as if it were a `Sequence`.
  59. //! @include example/ext/boost/mpl/vector/iterable.cpp
  60. //!
  61. //! 4. `Searchable`\n
  62. //! A MPL vector can be searched as if it were a tuple containing
  63. //! `hana::type`s.
  64. //! @include example/ext/boost/mpl/vector/searchable.cpp
  65. //!
  66. //!
  67. //! Conversion from any `Foldable`
  68. //! ------------------------------
  69. //! A MPL vector can be created from any `Foldable`. More precisely,
  70. //! for a `Foldable` `xs` whose linearization is `[x1, ..., xn]`,
  71. //! @code
  72. //! to<ext::boost::mpl::vector_tag>(xs) == mpl::vector<t1, ..., tn>
  73. //! @endcode
  74. //! where `tk` is the type of `xk`, or the type contained in `xk` if
  75. //! `xk` is a `hana::type`.
  76. //! @warning
  77. //! The limitations on the size of `mpl::vector`s are inherited by
  78. //! this conversion utility, and hence trying to convert a `Foldable`
  79. //! containing more than [BOOST_MPL_LIMIT_VECTOR_SIZE][1] elements
  80. //! is an error.
  81. //! @include example/ext/boost/mpl/vector/conversion.cpp
  82. //!
  83. //! [1]: http://www.boost.org/doc/libs/release/libs/mpl/doc/refmanual/limit-vector-size.html
  84. template <typename ...T>
  85. struct vector { };
  86. }}
  87. #endif
  88. namespace boost { namespace hana {
  89. namespace ext { namespace boost { namespace mpl {
  90. using vector_tag = ::boost::mpl::sequence_tag< ::boost::mpl::vector<>>::type;
  91. }}}
  92. namespace mpl_detail {
  93. // When `BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES` is not defined (e.g. on
  94. // MSVC), different MPL sequences (like vector0 and vector1) have different
  95. // tags, so we need to take that into account when we compare them.
  96. #ifndef BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES
  97. template <typename T1, typename T2>
  98. struct is_same_mpl_vector_tag : std::false_type { };
  99. template <template <long> class Tag, long x, long y>
  100. struct is_same_mpl_vector_tag<Tag<x>, Tag<y>> : std::true_type { };
  101. #else
  102. template <typename T1, typename T2>
  103. struct is_same_mpl_vector_tag : std::is_same<T1, T2> { };
  104. #endif
  105. }
  106. template <typename T>
  107. struct tag_of<T, when<
  108. mpl_detail::is_same_mpl_vector_tag<
  109. typename ::boost::mpl::sequence_tag<T>::type,
  110. ::boost::mpl::sequence_tag< ::boost::mpl::vector<>>::type
  111. >::value
  112. >> {
  113. using type = ext::boost::mpl::vector_tag;
  114. };
  115. //////////////////////////////////////////////////////////////////////////
  116. // Comparable
  117. //////////////////////////////////////////////////////////////////////////
  118. template <>
  119. struct equal_impl<ext::boost::mpl::vector_tag, ext::boost::mpl::vector_tag> {
  120. template <typename Xs, typename Ys>
  121. static constexpr auto apply(Xs const&, Ys const&) {
  122. return typename ::boost::mpl::equal<Xs, Ys>::type{};
  123. }
  124. };
  125. //////////////////////////////////////////////////////////////////////////
  126. // Foldable
  127. //////////////////////////////////////////////////////////////////////////
  128. template <>
  129. struct length_impl<ext::boost::mpl::vector_tag> {
  130. template <typename Xs>
  131. static constexpr auto apply(Xs const&) {
  132. return hana::size_c< ::boost::mpl::size<Xs>::type::value>;
  133. }
  134. };
  135. //////////////////////////////////////////////////////////////////////////
  136. // Iterable
  137. //////////////////////////////////////////////////////////////////////////
  138. template <>
  139. struct at_impl<ext::boost::mpl::vector_tag> {
  140. template <typename Ts, typename N>
  141. static constexpr auto apply(Ts const&, N const&) {
  142. constexpr std::size_t n = N::value;
  143. using T = typename ::boost::mpl::at_c<Ts, n>::type;
  144. return hana::type_c<T>;
  145. }
  146. };
  147. template <>
  148. struct drop_front_impl<ext::boost::mpl::vector_tag> {
  149. template <std::size_t n, typename Xs, std::size_t ...i>
  150. static constexpr auto drop_front_helper(Xs const&, std::index_sequence<i...>) {
  151. return boost::mpl::vector<
  152. typename boost::mpl::at_c<Xs, n + i>::type...
  153. >{};
  154. }
  155. template <typename Xs, typename N>
  156. static constexpr auto apply(Xs const& xs, N const&) {
  157. constexpr std::size_t n = N::value;
  158. constexpr std::size_t len = decltype(hana::length(xs))::value;
  159. return drop_front_helper<n>(xs,
  160. std::make_index_sequence<(n < len ? len - n : 0)>{});
  161. }
  162. };
  163. template <>
  164. struct is_empty_impl<ext::boost::mpl::vector_tag> {
  165. template <typename xs>
  166. static constexpr auto apply(xs)
  167. { return typename ::boost::mpl::empty<xs>::type{}; }
  168. };
  169. //////////////////////////////////////////////////////////////////////////
  170. // Conversion from a Foldable
  171. //////////////////////////////////////////////////////////////////////////
  172. template <typename F>
  173. struct to_impl<ext::boost::mpl::vector_tag, F, when<hana::Foldable<F>::value>> {
  174. template <typename Xs>
  175. static constexpr auto apply(Xs const& xs) {
  176. auto vector_type = hana::unpack(xs, hana::template_<boost::mpl::vector>);
  177. return typename decltype(vector_type)::type{};
  178. }
  179. };
  180. }} // end namespace boost::hana
  181. #endif // !BOOST_HANA_EXT_BOOST_MPL_VECTOR_HPP