functor.hpp 9.2 KB

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