monoid.hpp 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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_MONOID_HPP
  5. #define BOOST_HANA_TEST_LAWS_MONOID_HPP
  6. #include <boost/hana/assert.hpp>
  7. #include <boost/hana/bool.hpp>
  8. #include <boost/hana/concept/comparable.hpp>
  9. #include <boost/hana/core/when.hpp>
  10. #include <boost/hana/functional/capture.hpp>
  11. #include <boost/hana/lazy.hpp>
  12. #include <boost/hana/concept/monoid.hpp>
  13. #include <laws/base.hpp>
  14. namespace boost { namespace hana { namespace test {
  15. template <typename M, typename = when<true>>
  16. struct TestMonoid : TestMonoid<M, laws> {
  17. using TestMonoid<M, laws>::TestMonoid;
  18. };
  19. template <typename M>
  20. struct TestMonoid<M, laws> {
  21. template <typename Xs>
  22. TestMonoid(Xs xs) {
  23. #ifdef BOOST_HANA_WORKAROUND_MSVC_DECLTYPEAUTO_RETURNTYPE_662735
  24. zero<M>(); // force adding zero<M>'s member function to pending temploid list
  25. #endif
  26. hana::for_each(xs, hana::capture(xs)([](auto xs, auto a) {
  27. static_assert(Monoid<decltype(a)>{}, "");
  28. // left identity
  29. BOOST_HANA_CHECK(hana::equal(
  30. hana::plus(zero<M>(), a),
  31. a
  32. ));
  33. // right identity
  34. BOOST_HANA_CHECK(hana::equal(
  35. hana::plus(a, zero<M>()),
  36. a
  37. ));
  38. hana::for_each(xs,
  39. hana::capture(xs, a)([](auto xs, auto a, auto b) {
  40. hana::for_each(xs,
  41. hana::capture(a, b)([](auto a, auto b, auto c) {
  42. // associativity
  43. BOOST_HANA_CHECK(equal(
  44. hana::plus(a, hana::plus(b, c)),
  45. hana::plus(hana::plus(a, b), c)
  46. ));
  47. }));
  48. }));
  49. }));
  50. }
  51. };
  52. template <typename C>
  53. struct TestMonoid<C, when<Constant<C>::value>>
  54. : TestMonoid<C, laws>
  55. {
  56. template <typename Xs>
  57. TestMonoid(Xs xs) : TestMonoid<C, laws>{xs} {
  58. BOOST_HANA_CHECK(hana::equal(
  59. hana::value(zero<C>()),
  60. zero<typename C::value_type>()
  61. ));
  62. foreach2(xs, [](auto x, auto y) {
  63. BOOST_HANA_CHECK(hana::equal(
  64. hana::plus(hana::value(x), hana::value(y)),
  65. hana::value(hana::plus(x, y))
  66. ));
  67. });
  68. }
  69. };
  70. }}} // end namespace boost::hana::test
  71. #endif // !BOOST_HANA_TEST_LAWS_MONOID_HPP