• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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