1 // Copyright Louis Dionne 2013-2017 2 // Distributed under the Boost Software License, Version 1.0. 3 // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 4 5 #ifndef TEST_SUPPORT_SEQ_HPP 6 #define TEST_SUPPORT_SEQ_HPP 7 8 #include <boost/hana/fwd/at.hpp> 9 #include <boost/hana/fwd/concept/sequence.hpp> 10 #include <boost/hana/fwd/core/make.hpp> 11 #include <boost/hana/fwd/drop_front.hpp> 12 #include <boost/hana/fwd/fold_left.hpp> 13 #include <boost/hana/fwd/is_empty.hpp> 14 #include <boost/hana/fwd/length.hpp> 15 #include <boost/hana/tuple.hpp> 16 #include <boost/hana/unpack.hpp> 17 18 19 struct Seq; 20 21 template <typename Storage> 22 struct seq_type { seq_typeseq_type23 explicit constexpr seq_type(Storage s) : storage(s) { } 24 Storage storage; 25 using hana_tag = Seq; 26 }; 27 28 struct seq_t { 29 template <typename ...Xs> operator ()seq_t30 constexpr auto operator()(Xs&& ...xs) const { 31 auto storage = boost::hana::make_tuple(xs...); 32 return seq_type<decltype(storage)>(storage); 33 } 34 }; 35 constexpr seq_t seq{}; 36 37 namespace boost { namespace hana { 38 ////////////////////////////////////////////////////////////////////////// 39 // Foldable 40 // 41 // Define either one to select which MCD is used: 42 // BOOST_HANA_TEST_FOLDABLE_FOLD_LEFT_MCD 43 // BOOST_HANA_TEST_FOLDABLE_UNPACK_MCD 44 // BOOST_HANA_TEST_FOLDABLE_ITERABLE_MCD 45 // 46 // If neither is defined, the MCD used is unspecified. 47 ////////////////////////////////////////////////////////////////////////// 48 #ifdef BOOST_HANA_TEST_FOLDABLE_FOLD_LEFT_MCD 49 template <> 50 struct fold_left_impl<Seq> { 51 template <typename Xs, typename S, typename F> applyboost::hana::fold_left_impl52 static constexpr auto apply(Xs xs, S s, F f) { 53 return hana::fold_left(xs.storage, s, f); 54 } 55 56 template <typename Xs, typename F> applyboost::hana::fold_left_impl57 static constexpr auto apply(Xs xs, F f) { 58 return hana::fold_left(xs.storage, f); 59 } 60 }; 61 #elif defined(BOOST_HANA_TEST_FOLDABLE_ITERABLE_MCD) 62 template <> 63 struct length_impl<Seq> { 64 template <typename Xs> 65 static constexpr auto apply(Xs const& xs) { 66 return hana::length(xs.storage); 67 } 68 }; 69 #else 70 template <> 71 struct unpack_impl<Seq> { 72 template <typename Xs, typename F> 73 static constexpr auto apply(Xs xs, F f) 74 { return hana::unpack(xs.storage, f); } 75 }; 76 #endif 77 78 ////////////////////////////////////////////////////////////////////////// 79 // Iterable 80 ////////////////////////////////////////////////////////////////////////// 81 template <> 82 struct at_impl<Seq> { 83 template <typename Xs, typename N> applyboost::hana::at_impl84 static constexpr decltype(auto) apply(Xs&& xs, N&& n) { 85 return hana::at(static_cast<Xs&&>(xs).storage, n); 86 } 87 }; 88 89 template <> 90 struct drop_front_impl<Seq> { 91 template <typename Xs, typename N> applyboost::hana::drop_front_impl92 static constexpr auto apply(Xs xs, N n) { 93 return hana::unpack(hana::drop_front(xs.storage, n), ::seq); 94 } 95 }; 96 97 template <> 98 struct is_empty_impl<Seq> { 99 template <typename Xs> applyboost::hana::is_empty_impl100 static constexpr auto apply(Xs xs) { 101 return hana::is_empty(xs.storage); 102 } 103 }; 104 105 ////////////////////////////////////////////////////////////////////////// 106 // Sequence 107 ////////////////////////////////////////////////////////////////////////// 108 template <> 109 struct Sequence<Seq> { 110 static constexpr bool value = true; 111 }; 112 113 template <> 114 struct make_impl<Seq> { 115 template <typename ...Xs> applyboost::hana::make_impl116 static constexpr auto apply(Xs&& ...xs) { 117 return ::seq(static_cast<Xs&&>(xs)...); 118 } 119 }; 120 }} // end namespace boost::hana 121 122 #endif // !TEST_SUPPORT_SEQ_HPP 123