| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- /*!
- @file
- Adapts `boost::mpl::vector` for use with Hana.
- Copyright Louis Dionne 2013-2022
- Distributed under the Boost Software License, Version 1.0.
- (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
- */
- #ifndef BOOST_HANA_EXT_BOOST_MPL_VECTOR_HPP
- #define BOOST_HANA_EXT_BOOST_MPL_VECTOR_HPP
- #include <boost/hana/concept/foldable.hpp>
- #include <boost/hana/config.hpp>
- #include <boost/hana/core/when.hpp>
- #include <boost/hana/ext/boost/mpl/integral_c.hpp>
- #include <boost/hana/fwd/at.hpp>
- #include <boost/hana/fwd/core/to.hpp>
- #include <boost/hana/fwd/core/tag_of.hpp>
- #include <boost/hana/fwd/drop_front.hpp>
- #include <boost/hana/fwd/equal.hpp>
- #include <boost/hana/fwd/is_empty.hpp>
- #include <boost/hana/fwd/less.hpp>
- #include <boost/hana/integral_constant.hpp>
- #include <boost/hana/length.hpp>
- #include <boost/hana/type.hpp>
- #include <boost/hana/unpack.hpp>
- #include <boost/mpl/at.hpp>
- #include <boost/mpl/empty.hpp>
- #include <boost/mpl/equal.hpp>
- #include <boost/mpl/sequence_tag.hpp>
- #include <boost/mpl/size.hpp>
- #include <boost/mpl/vector.hpp>
- #include <cstddef>
- #include <type_traits>
- #include <utility>
- #ifdef BOOST_HANA_DOXYGEN_INVOKED
- namespace boost { namespace mpl {
- //! @ingroup group-ext-mpl
- //! Adapter for Boost.MPL vectors.
- //!
- //!
- //! Modeled concepts
- //! ----------------
- //! It is possible for MPL vectors to model a couple of concepts.
- //! However, because they are only able to hold types, they lack
- //! the generality required to model concepts like `Functor`,
- //! `Sequence` and other related concepts.
- //!
- //! 1. `Comparable`\n
- //! Two MPL vectors are equal if and only if they contain the same
- //! number of types, and if all those types are equal.
- //! @include example/ext/boost/mpl/vector/comparable.cpp
- //!
- //! 2. `Foldable`\n
- //! Folding a MPL vector is equivalent to folding it as a `Sequence`.
- //! @include example/ext/boost/mpl/vector/foldable.cpp
- //!
- //! 3. `Iterable`\n
- //! Iterating over a MPL vector is just iterating over each of the
- //! types it contains, as if it were a `Sequence`.
- //! @include example/ext/boost/mpl/vector/iterable.cpp
- //!
- //! 4. `Searchable`\n
- //! A MPL vector can be searched as if it were a tuple containing
- //! `hana::type`s.
- //! @include example/ext/boost/mpl/vector/searchable.cpp
- //!
- //!
- //! Conversion from any `Foldable`
- //! ------------------------------
- //! A MPL vector can be created from any `Foldable`. More precisely,
- //! for a `Foldable` `xs` whose linearization is `[x1, ..., xn]`,
- //! @code
- //! to<ext::boost::mpl::vector_tag>(xs) == mpl::vector<t1, ..., tn>
- //! @endcode
- //! where `tk` is the type of `xk`, or the type contained in `xk` if
- //! `xk` is a `hana::type`.
- //! @warning
- //! The limitations on the size of `mpl::vector`s are inherited by
- //! this conversion utility, and hence trying to convert a `Foldable`
- //! containing more than [BOOST_MPL_LIMIT_VECTOR_SIZE][1] elements
- //! is an error.
- //! @include example/ext/boost/mpl/vector/conversion.cpp
- //!
- //! [1]: http://www.boost.org/doc/libs/release/libs/mpl/doc/refmanual/limit-vector-size.html
- template <typename ...T>
- struct vector { };
- }}
- #endif
- namespace boost { namespace hana {
- namespace ext { namespace boost { namespace mpl {
- using vector_tag = ::boost::mpl::sequence_tag< ::boost::mpl::vector<>>::type;
- }}}
- namespace mpl_detail {
- // When `BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES` is not defined (e.g. on
- // MSVC), different MPL sequences (like vector0 and vector1) have different
- // tags, so we need to take that into account when we compare them.
- #ifndef BOOST_MPL_CFG_TYPEOF_BASED_SEQUENCES
- template <typename T1, typename T2>
- struct is_same_mpl_vector_tag : std::false_type { };
- template <template <long> class Tag, long x, long y>
- struct is_same_mpl_vector_tag<Tag<x>, Tag<y>> : std::true_type { };
- #else
- template <typename T1, typename T2>
- struct is_same_mpl_vector_tag : std::is_same<T1, T2> { };
- #endif
- }
- template <typename T>
- struct tag_of<T, when<
- mpl_detail::is_same_mpl_vector_tag<
- typename ::boost::mpl::sequence_tag<T>::type,
- ::boost::mpl::sequence_tag< ::boost::mpl::vector<>>::type
- >::value
- >> {
- using type = ext::boost::mpl::vector_tag;
- };
- //////////////////////////////////////////////////////////////////////////
- // Comparable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct equal_impl<ext::boost::mpl::vector_tag, ext::boost::mpl::vector_tag> {
- template <typename Xs, typename Ys>
- static constexpr auto apply(Xs const&, Ys const&) {
- return typename ::boost::mpl::equal<Xs, Ys>::type{};
- }
- };
- //////////////////////////////////////////////////////////////////////////
- // Foldable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct length_impl<ext::boost::mpl::vector_tag> {
- template <typename Xs>
- static constexpr auto apply(Xs const&) {
- return hana::size_c< ::boost::mpl::size<Xs>::type::value>;
- }
- };
- //////////////////////////////////////////////////////////////////////////
- // Iterable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct at_impl<ext::boost::mpl::vector_tag> {
- template <typename Ts, typename N>
- static constexpr auto apply(Ts const&, N const&) {
- constexpr std::size_t n = N::value;
- using T = typename ::boost::mpl::at_c<Ts, n>::type;
- return hana::type_c<T>;
- }
- };
- template <>
- struct drop_front_impl<ext::boost::mpl::vector_tag> {
- template <std::size_t n, typename Xs, std::size_t ...i>
- static constexpr auto drop_front_helper(Xs const&, std::index_sequence<i...>) {
- return boost::mpl::vector<
- typename boost::mpl::at_c<Xs, n + i>::type...
- >{};
- }
- template <typename Xs, typename N>
- static constexpr auto apply(Xs const& xs, N const&) {
- constexpr std::size_t n = N::value;
- constexpr std::size_t len = decltype(hana::length(xs))::value;
- return drop_front_helper<n>(xs,
- std::make_index_sequence<(n < len ? len - n : 0)>{});
- }
- };
- template <>
- struct is_empty_impl<ext::boost::mpl::vector_tag> {
- template <typename xs>
- static constexpr auto apply(xs)
- { return typename ::boost::mpl::empty<xs>::type{}; }
- };
- //////////////////////////////////////////////////////////////////////////
- // Conversion from a Foldable
- //////////////////////////////////////////////////////////////////////////
- template <typename F>
- struct to_impl<ext::boost::mpl::vector_tag, F, when<hana::Foldable<F>::value>> {
- template <typename Xs>
- static constexpr auto apply(Xs const& xs) {
- auto vector_type = hana::unpack(xs, hana::template_<boost::mpl::vector>);
- return typename decltype(vector_type)::type{};
- }
- };
- }} // end namespace boost::hana
- #endif // !BOOST_HANA_EXT_BOOST_MPL_VECTOR_HPP
|