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 BOOST_HANA_TEST_LAWS_ITERABLE_HPP 6 #define BOOST_HANA_TEST_LAWS_ITERABLE_HPP 7 8 #include <boost/hana/any_of.hpp> 9 #include <boost/hana/assert.hpp> 10 #include <boost/hana/at.hpp> 11 #include <boost/hana/back.hpp> 12 #include <boost/hana/bool.hpp> 13 #include <boost/hana/concept/comparable.hpp> 14 #include <boost/hana/concept/foldable.hpp> 15 #include <boost/hana/concept/sequence.hpp> 16 #include <boost/hana/core/make.hpp> 17 #include <boost/hana/core/to.hpp> 18 #include <boost/hana/core/when.hpp> 19 #include <boost/hana/drop_front.hpp> 20 #include <boost/hana/drop_front_exactly.hpp> 21 #include <boost/hana/equal.hpp> 22 #include <boost/hana/eval_if.hpp> 23 #include <boost/hana/find_if.hpp> 24 #include <boost/hana/for_each.hpp> 25 #include <boost/hana/front.hpp> 26 #include <boost/hana/functional/always.hpp> 27 #include <boost/hana/functional/capture.hpp> 28 #include <boost/hana/integral_constant.hpp> 29 #include <boost/hana/is_empty.hpp> 30 #include <boost/hana/lazy.hpp> 31 #include <boost/hana/length.hpp> 32 #include <boost/hana/minus.hpp> 33 #include <boost/hana/not.hpp> 34 #include <boost/hana/optional.hpp> 35 #include <boost/hana/range.hpp> 36 #include <boost/hana/tuple.hpp> 37 38 #include <laws/base.hpp> 39 40 41 namespace boost { namespace hana { namespace test { 42 template <typename It, typename = hana::when<true>> 43 struct TestIterable : TestIterable<It, laws> { 44 using TestIterable<It, laws>::TestIterable; 45 }; 46 47 template <typename It> 48 struct TestIterable<It, laws> { 49 template <typename Xs> TestIterableboost::hana::test::TestIterable50 TestIterable(Xs xs) { 51 hana::for_each(xs, [](auto xs) { 52 static_assert(Iterable<decltype(xs)>{}, ""); 53 54 BOOST_HANA_CONSTANT_CHECK( 55 hana::is_empty(xs) ^iff^ hana::is_empty(hana::to<tuple_tag>(xs)) 56 ); 57 58 only_when_(hana::not_(hana::is_empty(xs)), hana::make_lazy([](auto xs) { 59 BOOST_HANA_CHECK(hana::equal( 60 hana::front(xs), 61 hana::front(hana::to<tuple_tag>(xs)) 62 )); 63 64 BOOST_HANA_CHECK(hana::equal( 65 hana::to<tuple_tag>(hana::drop_front_exactly(xs)), 66 hana::drop_front_exactly(hana::to<tuple_tag>(xs)) 67 )); 68 69 // methods 70 // back(xs) == at(xs, length(xs)-1) 71 BOOST_HANA_CHECK(hana::equal( 72 hana::back(xs), 73 hana::at(xs, hana::minus(hana::length(xs), hana::size_c<1>)) 74 )); 75 76 })(xs)); 77 78 // drop_front(xs, 0) == xs 79 BOOST_HANA_CHECK(hana::equal( 80 hana::drop_front(xs, size_c<0>), 81 xs 82 )); 83 84 // at(xs, n) == front(drop_front(xs, n)) 85 hana::for_each(hana::make_range(size_c<0>, hana::length(xs)), 86 hana::capture(xs)([](auto xs, auto n) { 87 BOOST_HANA_CHECK(hana::equal( 88 hana::at(xs, n), 89 hana::front(hana::drop_front(xs, n)) 90 )); 91 })); 92 93 // Searchable 94 hana::eval_if(hana::is_empty(xs), 95 hana::make_lazy([](auto xs) { 96 BOOST_HANA_CONSTANT_CHECK( 97 hana::not_(hana::any_of(xs, hana::always(true_c))) 98 ); 99 100 BOOST_HANA_CONSTANT_CHECK(hana::equal( 101 hana::find_if(xs, hana::always(true_c)), 102 nothing 103 )); 104 })(xs), 105 hana::make_lazy([](auto xs) { 106 BOOST_HANA_CHECK( 107 hana::any_of(xs, hana::always(true_c)) 108 ); 109 BOOST_HANA_CHECK( 110 hana::not_(hana::any_of(xs, hana::always(false_c))) 111 ); 112 113 BOOST_HANA_CHECK(hana::equal( 114 hana::find_if(xs, hana::always(true_c)), 115 hana::just(hana::front(xs)) 116 )); 117 })(xs) 118 ); 119 120 }); 121 } 122 }; 123 124 template <typename S> 125 struct TestIterable<S, when<Sequence<S>::value>> 126 : TestIterable<S, laws> 127 { 128 template <int i> 129 using x = ct_eq<i>; 130 131 template <int i = 0> 132 struct invalid { }; 133 134 struct undefined { }; 135 136 template <typename Xs> TestIterableboost::hana::test::TestIterable137 TestIterable(Xs xs) : TestIterable<S, laws>{xs} { 138 constexpr auto list = make<S>; 139 140 ////////////////////////////////////////////////////////////////// 141 // front 142 ////////////////////////////////////////////////////////////////// 143 BOOST_HANA_CONSTANT_CHECK(equal( 144 front(list(x<0>{})), 145 x<0>{} 146 )); 147 BOOST_HANA_CONSTANT_CHECK(equal( 148 front(list(x<0>{}, invalid<>{})), 149 x<0>{} 150 )); 151 BOOST_HANA_CONSTANT_CHECK(equal( 152 front(list(x<0>{}, invalid<1>{}, invalid<2>{})), 153 x<0>{} 154 )); 155 156 BOOST_HANA_CONSTEXPR_CHECK(equal( 157 front(list(1)), 1 158 )); 159 BOOST_HANA_CONSTEXPR_CHECK(equal( 160 front(list(1, '2')), 1 161 )); 162 BOOST_HANA_CONSTEXPR_CHECK(equal( 163 front(list(1, '2', 3.3)), 1 164 )); 165 166 ////////////////////////////////////////////////////////////////// 167 // back 168 ////////////////////////////////////////////////////////////////// 169 BOOST_HANA_CONSTANT_CHECK(equal( 170 back(list(x<0>{})), 171 x<0>{} 172 )); 173 BOOST_HANA_CONSTANT_CHECK(equal( 174 back(list(invalid<0>{}, x<1>{})), 175 x<1>{} 176 )); 177 BOOST_HANA_CONSTANT_CHECK(equal( 178 back(list(invalid<0>{}, invalid<1>{}, x<2>{})), 179 x<2>{} 180 )); 181 182 BOOST_HANA_CONSTEXPR_CHECK(equal( 183 back(list(1)), 1 184 )); 185 BOOST_HANA_CONSTEXPR_CHECK(equal( 186 back(list(1, '2')), '2' 187 )); 188 BOOST_HANA_CONSTEXPR_CHECK(equal( 189 back(list(1, '2', 3.3)), 3.3 190 )); 191 } 192 }; 193 }}} // end namespace boost::hana::test 194 195 #endif // !BOOST_HANA_TEST_LAWS_ITERABLE_HPP 196