first_of.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*=============================================================================
  2. Copyright (c) 2017 Paul Fultz II
  3. first_of.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/first_of.hpp>
  8. #include <boost/hof/static.hpp>
  9. #include <boost/hof/lambda.hpp>
  10. #include <boost/hof/function.hpp>
  11. #include <memory>
  12. #include "test.hpp"
  13. namespace conditional_test {
  14. #define CONDITIONAL_FUNCTION(n) \
  15. struct t ## n {}; \
  16. struct f ## n \
  17. { \
  18. constexpr int operator()(t ## n) const \
  19. { \
  20. return n; \
  21. } \
  22. };
  23. CONDITIONAL_FUNCTION(1)
  24. CONDITIONAL_FUNCTION(2)
  25. CONDITIONAL_FUNCTION(3)
  26. #define CONDITIONAL_MOVE_FUNCTION(n) \
  27. struct t_move ## n {}; \
  28. struct f_move ## n \
  29. { \
  30. std::unique_ptr<int> i;\
  31. f_move ## n(int ip) : i(new int(ip)) {}; \
  32. int operator()(t_move ## n) const \
  33. { \
  34. return *i; \
  35. } \
  36. };
  37. CONDITIONAL_MOVE_FUNCTION(1)
  38. CONDITIONAL_MOVE_FUNCTION(2)
  39. CONDITIONAL_MOVE_FUNCTION(3)
  40. struct ff
  41. {
  42. constexpr int operator()(t2) const
  43. {
  44. return 500;
  45. }
  46. };
  47. static constexpr boost::hof::static_<boost::hof::first_of_adaptor<f1, f2, f3, ff> > f = {};
  48. BOOST_HOF_STATIC_FUNCTION(f_constexpr) = boost::hof::first_of_adaptor<f1, f2, f3, ff>();
  49. BOOST_HOF_TEST_CASE()
  50. {
  51. BOOST_HOF_TEST_CHECK(f(t1()) == 1);
  52. BOOST_HOF_TEST_CHECK(f(t2()) == 2);
  53. BOOST_HOF_TEST_CHECK(f(t3()) == 3);
  54. BOOST_HOF_STATIC_TEST_CHECK(f_constexpr(t1()) == 1);
  55. BOOST_HOF_STATIC_TEST_CHECK(f_constexpr(t2()) == 2);
  56. BOOST_HOF_STATIC_TEST_CHECK(f_constexpr(t3()) == 3);
  57. }
  58. BOOST_HOF_TEST_CASE()
  59. {
  60. BOOST_HOF_TEST_CHECK(boost::hof::first_of(f1{}, f2{})(t1()) == 1);
  61. BOOST_HOF_TEST_CHECK(boost::hof::first_of(f1{}, f2{})(t2()) == 2);
  62. BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(f1{}, f2{})(t1()) == 1);
  63. BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(f1{}, f2{})(t2()) == 2);
  64. }
  65. #if (defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7)
  66. #else
  67. BOOST_HOF_TEST_CASE()
  68. {
  69. BOOST_HOF_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f1{}, f2{}))(t1()) == 1);
  70. BOOST_HOF_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f1{}, f2{}))(t2()) == 2);
  71. BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f1{}, f2{}))(t1()) == 1);
  72. BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f1{}, f2{}))(t2()) == 2);
  73. }
  74. BOOST_HOF_TEST_CASE()
  75. {
  76. BOOST_HOF_TEST_CHECK(boost::hof::first_of(f1{}, boost::hof::first_of(f2{}, f3{}))(t1()) == 1);
  77. BOOST_HOF_TEST_CHECK(boost::hof::first_of(f1{}, boost::hof::first_of(f2{}, f3{}))(t2()) == 2);
  78. BOOST_HOF_TEST_CHECK(boost::hof::first_of(f1{}, boost::hof::first_of(f2{}, f3{}))(t3()) == 3);
  79. BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(f1{}, boost::hof::first_of(f2{}, f3{}))(t1()) == 1);
  80. BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(f1{}, boost::hof::first_of(f2{}, f3{}))(t2()) == 2);
  81. BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(f1{}, boost::hof::first_of(f2{}, f3{}))(t3()) == 3);
  82. }
  83. BOOST_HOF_TEST_CASE()
  84. {
  85. BOOST_HOF_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f2{}, f3{}))(t1()) == 1);
  86. BOOST_HOF_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f2{}, f3{}))(t2()) == 2);
  87. BOOST_HOF_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f2{}, f3{}))(t3()) == 3);
  88. BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f2{}, f3{}))(t1()) == 1);
  89. BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f2{}, f3{}))(t2()) == 2);
  90. BOOST_HOF_STATIC_TEST_CHECK(boost::hof::first_of(boost::hof::first_of(f1{}, f2{}), boost::hof::first_of(f2{}, f3{}))(t3()) == 3);
  91. }
  92. #endif
  93. BOOST_HOF_TEST_CASE()
  94. {
  95. auto f_move_local = boost::hof::first_of(f_move1(1), f_move2(2), f_move3(3));
  96. STATIC_ASSERT_MOVE_ONLY(decltype(f_move_local));
  97. BOOST_HOF_TEST_CHECK(f_move_local(t_move1()) == 1);
  98. BOOST_HOF_TEST_CHECK(f_move_local(t_move2()) == 2);
  99. BOOST_HOF_TEST_CHECK(f_move_local(t_move3()) == 3);
  100. }
  101. #ifndef _MSC_VER
  102. static constexpr auto lam = boost::hof::first_of(
  103. BOOST_HOF_STATIC_LAMBDA(t1)
  104. {
  105. return 1;
  106. },
  107. BOOST_HOF_STATIC_LAMBDA(t2)
  108. {
  109. return 2;
  110. },
  111. BOOST_HOF_STATIC_LAMBDA(t3)
  112. {
  113. return 3;
  114. }
  115. );
  116. BOOST_HOF_TEST_CASE()
  117. {
  118. BOOST_HOF_TEST_CHECK(lam(t1()) == 1);
  119. BOOST_HOF_TEST_CHECK(lam(t2()) == 2);
  120. BOOST_HOF_TEST_CHECK(lam(t3()) == 3);
  121. }
  122. #endif
  123. BOOST_HOF_STATIC_LAMBDA_FUNCTION(static_fun) = boost::hof::first_of(
  124. [](t1)
  125. {
  126. return 1;
  127. },
  128. [](t2)
  129. {
  130. return 2;
  131. },
  132. [](t3)
  133. {
  134. return 3;
  135. }
  136. );
  137. BOOST_HOF_TEST_CASE()
  138. {
  139. BOOST_HOF_TEST_CHECK(static_fun(t1()) == 1);
  140. BOOST_HOF_TEST_CHECK(static_fun(t2()) == 2);
  141. BOOST_HOF_TEST_CHECK(static_fun(t3()) == 3);
  142. }
  143. BOOST_HOF_TEST_CASE()
  144. {
  145. BOOST_HOF_TEST_CHECK(boost::hof::first_of(boost::hof::identity, boost::hof::identity)(3) == 3);
  146. }
  147. template<class T>
  148. struct throw_fo
  149. {
  150. void operator()(T) const {}
  151. };
  152. template<class T>
  153. struct no_throw_fo
  154. {
  155. void operator()(T) const noexcept {}
  156. };
  157. #if BOOST_HOF_HAS_NOEXCEPT_DEDUCTION
  158. BOOST_HOF_TEST_CASE()
  159. {
  160. typedef boost::hof::first_of_adaptor<throw_fo<t1>, no_throw_fo<t2>> fun;
  161. auto g = fun{};
  162. static_assert(noexcept(g(t2{})), "noexcept conditional");
  163. static_assert(!noexcept(g(t1{})), "noexcept conditional");
  164. static_assert(noexcept(fun{}(t2{})), "noexcept conditional");
  165. static_assert(!noexcept(fun{}(t1{})), "noexcept conditional");
  166. }
  167. BOOST_HOF_TEST_CASE()
  168. {
  169. typedef boost::hof::first_of_adaptor<no_throw_fo<t2>, throw_fo<t1>> fun;
  170. auto g = fun{};
  171. static_assert(noexcept(g(t2{})), "noexcept conditional");
  172. static_assert(!noexcept(g(t1{})), "noexcept conditional");
  173. static_assert(noexcept(fun{}(t2{})), "noexcept conditional");
  174. static_assert(!noexcept(fun{}(t1{})), "noexcept conditional");
  175. }
  176. BOOST_HOF_TEST_CASE()
  177. {
  178. static_assert(noexcept(boost::hof::first_of_adaptor<no_throw_fo<t2>, throw_fo<t1>>{}(t2{})), "noexcept conditional");
  179. static_assert(!noexcept(boost::hof::first_of_adaptor<no_throw_fo<t2>, throw_fo<t1>>{}(t1{})), "noexcept conditional");
  180. static_assert(noexcept(boost::hof::first_of(no_throw_fo<t2>{}, throw_fo<t1>{})(t2{})), "noexcept conditional");
  181. static_assert(!noexcept(boost::hof::first_of(no_throw_fo<t2>{}, throw_fo<t1>{})(t1{})), "noexcept conditional");
  182. }
  183. #endif
  184. }