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