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_FUNCTOR_HPP 6 #define BOOST_HANA_TEST_LAWS_FUNCTOR_HPP 7 8 #include <boost/hana/adjust.hpp> 9 #include <boost/hana/adjust_if.hpp> 10 #include <boost/hana/assert.hpp> 11 #include <boost/hana/bool.hpp> 12 #include <boost/hana/concept/comparable.hpp> 13 #include <boost/hana/concept/functor.hpp> 14 #include <boost/hana/concept/sequence.hpp> 15 #include <boost/hana/core/make.hpp> 16 #include <boost/hana/core/when.hpp> 17 #include <boost/hana/equal.hpp> 18 #include <boost/hana/eval_if.hpp> 19 #include <boost/hana/fill.hpp> 20 #include <boost/hana/for_each.hpp> 21 #include <boost/hana/functional/always.hpp> 22 #include <boost/hana/functional/capture.hpp> 23 #include <boost/hana/functional/compose.hpp> 24 #include <boost/hana/lazy.hpp> 25 #include <boost/hana/replace.hpp> 26 #include <boost/hana/replace_if.hpp> 27 #include <boost/hana/transform.hpp> 28 29 #include <laws/base.hpp> 30 31 32 namespace boost { namespace hana { namespace test { 33 template <typename F, typename = when<true>> 34 struct TestFunctor : TestFunctor<F, laws> { 35 using TestFunctor<F, laws>::TestFunctor; 36 }; 37 38 template <typename F> 39 struct TestFunctor<F, laws> { 40 template <typename Xs, typename Elements> TestFunctorboost::hana::test::TestFunctor41 TestFunctor(Xs xs, Elements elements) { 42 hana::for_each(xs, hana::capture(elements)([](auto elements, auto x) { 43 static_assert(Functor<decltype(x)>{}, ""); 44 45 test::_injection<0> f{}; 46 test::_injection<1> g{}; 47 48 // identity 49 BOOST_HANA_CHECK(hana::equal( 50 hana::transform(x, id), 51 x 52 )); 53 54 // composition 55 BOOST_HANA_CHECK(hana::equal( 56 hana::transform(x, hana::compose(f, g)), 57 hana::transform(hana::transform(x, g), f) 58 )); 59 60 // method definitions in terms of transform/adjust_if 61 hana::for_each(elements, hana::capture(x, f, elements)( 62 [](auto x, auto f, auto elements, auto value) { 63 BOOST_HANA_CHECK(hana::equal( 64 hana::adjust(x, value, f), 65 hana::adjust_if(x, hana::equal.to(value), f) 66 )); 67 68 hana::for_each(elements, hana::capture(x, value)( 69 [](auto x, auto oldval, auto newval) { 70 BOOST_HANA_CHECK(hana::equal( 71 hana::replace(x, oldval, newval), 72 hana::replace_if(x, hana::equal.to(oldval), newval) 73 )); 74 })); 75 })); 76 77 auto pred = hana::always(true_c); 78 BOOST_HANA_CHECK(hana::equal( 79 hana::adjust_if(x, pred, f), 80 hana::transform(x, [=](auto z) { 81 return hana::eval_if(pred(z), 82 hana::make_lazy(f)(z), 83 hana::make_lazy(z) 84 ); 85 }) 86 )); 87 88 test::_constant<0> v{}; 89 BOOST_HANA_CHECK(hana::equal( 90 hana::replace_if(x, pred, v), 91 hana::adjust_if(x, pred, hana::always(v)) 92 )); 93 94 BOOST_HANA_CHECK(hana::equal( 95 hana::fill(x, v), 96 hana::replace_if(x, hana::always(true_c), v) 97 )); 98 99 })); 100 } 101 }; 102 103 template <typename S> 104 struct TestFunctor<S, when<Sequence<S>::value>> 105 : TestFunctor<S, laws> 106 { 107 struct undefined { }; 108 109 template <typename Xs, typename Elements> TestFunctorboost::hana::test::TestFunctor110 TestFunctor(Xs xs, Elements elements) 111 : TestFunctor<S, laws>{xs, elements} 112 { 113 using test::ct_eq; 114 using test::cx_eq; 115 constexpr auto list = make<S>; 116 117 ////////////////////////////////////////////////////////////////// 118 // replace_if 119 ////////////////////////////////////////////////////////////////// 120 { 121 auto a = ct_eq<888>{}; 122 auto b = ct_eq<999>{}; 123 124 BOOST_HANA_CONSTANT_CHECK(hana::equal( 125 hana::replace_if(list(), undefined{}, undefined{}), 126 list() 127 )); 128 129 BOOST_HANA_CONSTANT_CHECK(hana::equal( 130 hana::replace_if(list(ct_eq<0>{}), equal.to(a), undefined{}), 131 list(ct_eq<0>{}) 132 )); 133 BOOST_HANA_CONSTANT_CHECK(hana::equal( 134 hana::replace_if(list(a), equal.to(a), b), 135 list(b) 136 )); 137 138 BOOST_HANA_CONSTANT_CHECK(hana::equal( 139 hana::replace_if(list(ct_eq<0>{}, ct_eq<1>{}), equal.to(a), undefined{}), 140 list(ct_eq<0>{}, ct_eq<1>{}) 141 )); 142 BOOST_HANA_CONSTANT_CHECK(hana::equal( 143 hana::replace_if(list(a, ct_eq<1>{}), equal.to(a), b), 144 list(b, ct_eq<1>{}) 145 )); 146 BOOST_HANA_CONSTANT_CHECK(hana::equal( 147 hana::replace_if(list(ct_eq<0>{}, a), equal.to(a), b), 148 list(ct_eq<0>{}, b) 149 )); 150 BOOST_HANA_CONSTANT_CHECK(hana::equal( 151 hana::replace_if(list(a, a), equal.to(a), b), 152 list(b, b) 153 )); 154 155 BOOST_HANA_CONSTANT_CHECK(hana::equal( 156 hana::replace_if(list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), equal.to(a), undefined{}), 157 list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}) 158 )); 159 BOOST_HANA_CONSTANT_CHECK(hana::equal( 160 hana::replace_if(list(a, ct_eq<1>{}, ct_eq<2>{}), equal.to(a), b), 161 list(b, ct_eq<1>{}, ct_eq<2>{}) 162 )); 163 BOOST_HANA_CONSTANT_CHECK(hana::equal( 164 hana::replace_if(list(ct_eq<0>{}, a, ct_eq<2>{}), equal.to(a), b), 165 list(ct_eq<0>{}, b, ct_eq<2>{}) 166 )); 167 BOOST_HANA_CONSTANT_CHECK(hana::equal( 168 hana::replace_if(list(ct_eq<0>{}, ct_eq<1>{}, a), equal.to(a), b), 169 list(ct_eq<0>{}, ct_eq<1>{}, b) 170 )); 171 BOOST_HANA_CONSTANT_CHECK(hana::equal( 172 hana::replace_if(list(a, ct_eq<1>{}, a), equal.to(a), b), 173 list(b, ct_eq<1>{}, b) 174 )); 175 176 BOOST_HANA_CONSTANT_CHECK(hana::equal( 177 hana::replace_if(list(a, ct_eq<1>{}, a, ct_eq<3>{}, a), equal.to(a), b), 178 list(b, ct_eq<1>{}, b, ct_eq<3>{}, b) 179 )); 180 } 181 182 ////////////////////////////////////////////////////////////////// 183 // replace 184 ////////////////////////////////////////////////////////////////// 185 { 186 auto a = ct_eq<888>{}; 187 auto b = ct_eq<999>{}; 188 189 BOOST_HANA_CONSTANT_CHECK(hana::equal( 190 hana::replace(list(), undefined{}, undefined{}), 191 list() 192 )); 193 194 BOOST_HANA_CONSTANT_CHECK(hana::equal( 195 hana::replace(list(ct_eq<0>{}), a, undefined{}), 196 list(ct_eq<0>{}) 197 )); 198 BOOST_HANA_CONSTANT_CHECK(hana::equal( 199 hana::replace(list(a), a, b), 200 list(b) 201 )); 202 203 BOOST_HANA_CONSTANT_CHECK(hana::equal( 204 hana::replace(list(ct_eq<0>{}, ct_eq<1>{}), a, undefined{}), 205 list(ct_eq<0>{}, ct_eq<1>{}) 206 )); 207 BOOST_HANA_CONSTANT_CHECK(hana::equal( 208 hana::replace(list(a, ct_eq<1>{}), a, b), 209 list(b, ct_eq<1>{}) 210 )); 211 BOOST_HANA_CONSTANT_CHECK(hana::equal( 212 hana::replace(list(ct_eq<0>{}, a), a, b), 213 list(ct_eq<0>{}, b) 214 )); 215 BOOST_HANA_CONSTANT_CHECK(hana::equal( 216 hana::replace(list(a, a), a, b), 217 list(b, b) 218 )); 219 220 BOOST_HANA_CONSTANT_CHECK(hana::equal( 221 hana::replace(list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}), a, undefined{}), 222 list(ct_eq<0>{}, ct_eq<1>{}, ct_eq<2>{}) 223 )); 224 BOOST_HANA_CONSTANT_CHECK(hana::equal( 225 hana::replace(list(a, ct_eq<1>{}, ct_eq<2>{}), a, b), 226 list(b, ct_eq<1>{}, ct_eq<2>{}) 227 )); 228 BOOST_HANA_CONSTANT_CHECK(hana::equal( 229 hana::replace(list(ct_eq<0>{}, a, ct_eq<2>{}), a, b), 230 list(ct_eq<0>{}, b, ct_eq<2>{}) 231 )); 232 BOOST_HANA_CONSTANT_CHECK(hana::equal( 233 hana::replace(list(ct_eq<0>{}, ct_eq<1>{}, a), a, b), 234 list(ct_eq<0>{}, ct_eq<1>{}, b) 235 )); 236 BOOST_HANA_CONSTANT_CHECK(hana::equal( 237 hana::replace(list(a, ct_eq<1>{}, a), a, b), 238 list(b, ct_eq<1>{}, b) 239 )); 240 241 BOOST_HANA_CONSTANT_CHECK(hana::equal( 242 hana::replace(list(a, ct_eq<1>{}, a, ct_eq<3>{}, a), a, b), 243 list(b, ct_eq<1>{}, b, ct_eq<3>{}, b) 244 )); 245 } 246 } 247 }; 248 }}} // end namespace boost::hana::test 249 250 #endif // !BOOST_HANA_TEST_LAWS_FUNCTOR_HPP 251