match.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*=============================================================================
  2. Copyright (c) 2017 Paul Fultz II
  3. match.cpp
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ==============================================================================*/
  7. #include <boost/hof/match.hpp>
  8. #include <boost/hof/static.hpp>
  9. #include <boost/hof/lambda.hpp>
  10. #include <boost/hof/placeholders.hpp>
  11. #include <boost/hof/limit.hpp>
  12. #include "test.hpp"
  13. #include <memory>
  14. namespace test1
  15. {
  16. struct int_class
  17. {
  18. int operator()(int) const
  19. {
  20. return 1;
  21. }
  22. };
  23. struct foo
  24. {};
  25. struct foo_class
  26. {
  27. foo operator()(foo) const
  28. {
  29. return foo();
  30. }
  31. };
  32. static constexpr boost::hof::static_<boost::hof::match_adaptor<int_class, foo_class> > fun = {};
  33. static_assert(std::is_same<int, decltype(fun(1))>::value, "Failed match");
  34. static_assert(std::is_same<foo, decltype(fun(foo()))>::value, "Failed match");
  35. }
  36. struct int_class
  37. {
  38. constexpr int operator()(int) const
  39. {
  40. return 1;
  41. }
  42. };
  43. struct foo
  44. {};
  45. struct foo_class
  46. {
  47. constexpr int operator()(foo) const
  48. {
  49. return 2;
  50. }
  51. };
  52. static constexpr boost::hof::match_adaptor<int_class, foo_class> fun = {};
  53. BOOST_HOF_TEST_CASE()
  54. {
  55. BOOST_HOF_TEST_CHECK(fun(1) == 1);
  56. BOOST_HOF_TEST_CHECK(fun(foo()) == 2);
  57. BOOST_HOF_STATIC_TEST_CHECK(fun(1) == 1);
  58. BOOST_HOF_STATIC_TEST_CHECK(fun(foo()) == 2);
  59. };
  60. BOOST_HOF_TEST_CASE()
  61. {
  62. BOOST_HOF_TEST_CHECK(boost::hof::reveal(fun)(1) == 1);
  63. BOOST_HOF_TEST_CHECK(boost::hof::reveal(fun)(foo()) == 2);
  64. BOOST_HOF_STATIC_TEST_CHECK(boost::hof::reveal(fun)(1) == 1);
  65. BOOST_HOF_STATIC_TEST_CHECK(boost::hof::reveal(fun)(foo()) == 2);
  66. };
  67. BOOST_HOF_TEST_CASE()
  68. {
  69. constexpr auto lam = boost::hof::match(
  70. BOOST_HOF_STATIC_LAMBDA(int) { return 1; },
  71. BOOST_HOF_STATIC_LAMBDA(foo) { return 2; }
  72. );
  73. BOOST_HOF_TEST_CHECK(lam(1) == 1);
  74. BOOST_HOF_TEST_CHECK(lam(foo()) == 2);
  75. };
  76. BOOST_HOF_TEST_CASE()
  77. {
  78. int i = 0;
  79. auto lam = boost::hof::match(
  80. [&](int) { return i+1; },
  81. [&](foo) { return i+2; }
  82. );
  83. // Disable this check on msvc, since lambdas might be default constructible
  84. #ifndef _MSC_VER
  85. STATIC_ASSERT_NOT_DEFAULT_CONSTRUCTIBLE(decltype(lam));
  86. #endif
  87. BOOST_HOF_TEST_CHECK(lam(1) == 1);
  88. BOOST_HOF_TEST_CHECK(lam(foo()) == 2);
  89. };
  90. BOOST_HOF_TEST_CASE()
  91. {
  92. struct not_default_constructible
  93. {
  94. int i;
  95. not_default_constructible(int x) : i(x)
  96. {}
  97. };
  98. STATIC_ASSERT_NOT_DEFAULT_CONSTRUCTIBLE(not_default_constructible);
  99. not_default_constructible ndc = not_default_constructible(0);
  100. auto lam = boost::hof::match(
  101. [&](int) { return ndc.i+1; },
  102. [&](foo) { return ndc.i+2; }
  103. );
  104. // Disable this check on msvc, since lambdas might be default constructible
  105. #ifndef _MSC_VER
  106. STATIC_ASSERT_NOT_DEFAULT_CONSTRUCTIBLE(decltype(lam));
  107. #endif
  108. BOOST_HOF_TEST_CHECK(lam(1) == 1);
  109. BOOST_HOF_TEST_CHECK(lam(foo()) == 2);
  110. };
  111. struct int_move_class
  112. {
  113. std::unique_ptr<int> i;
  114. int_move_class() : i(new int(1))
  115. {}
  116. int operator()(int) const
  117. {
  118. return *i;
  119. }
  120. };
  121. struct foo_move_class
  122. {
  123. std::unique_ptr<int> i;
  124. foo_move_class() : i(new int(2))
  125. {}
  126. int operator()(foo) const
  127. {
  128. return *i;
  129. }
  130. };
  131. BOOST_HOF_TEST_CASE()
  132. {
  133. auto fun_move = boost::hof::match(int_move_class(), foo_move_class());
  134. BOOST_HOF_TEST_CHECK(fun_move(1) == 1);
  135. BOOST_HOF_TEST_CHECK(fun_move(foo()) == 2);
  136. };
  137. BOOST_HOF_TEST_CASE()
  138. {
  139. const auto negate = (!boost::hof::_);
  140. const auto sub = (boost::hof::_ - boost::hof::_);
  141. BOOST_HOF_TEST_CHECK(boost::hof::match(negate, sub)(0) == negate(0));
  142. BOOST_HOF_TEST_CHECK(boost::hof::match(negate, sub)(0, 1) == sub(0, 1));
  143. }
  144. BOOST_HOF_TEST_CASE()
  145. {
  146. const auto negate = (!boost::hof::_1);
  147. const auto sub = (boost::hof::_1 - boost::hof::_2);
  148. BOOST_HOF_TEST_CHECK(boost::hof::match(negate, sub)(0) == negate(0));
  149. // This is test is disabled because its invalid. It is valid to give more
  150. // parameters than what are used by the placeholders. So negate(0, 1) is a
  151. // valid call, which makes the following test fail with ambigous overload.
  152. // BOOST_HOF_TEST_CHECK(boost::hof::match(negate, sub)(0, 1) == sub(0, 1));
  153. }
  154. BOOST_HOF_TEST_CASE()
  155. {
  156. const auto negate = boost::hof::limit_c<1>(!boost::hof::_1);
  157. const auto sub = boost::hof::limit_c<2>(boost::hof::_1 - boost::hof::_2);
  158. BOOST_HOF_TEST_CHECK(boost::hof::match(negate, sub)(0) == negate(0));
  159. // This test will pass because we have limited the number of parameters.
  160. BOOST_HOF_TEST_CHECK(boost::hof::match(negate, sub)(0, 1) == sub(0, 1));
  161. }