pred.hpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. #ifndef BOOST_LEAF_PRED_HPP_INCLUDED
  2. #define BOOST_LEAF_PRED_HPP_INCLUDED
  3. // Copyright 2018-2023 Emil Dotchevski and Reverge Studios, Inc.
  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. #include <boost/leaf/config.hpp>
  7. #include <boost/leaf/handle_errors.hpp>
  8. #if __cplusplus >= 201703L
  9. # define BOOST_LEAF_MATCH_ARGS(et,v1,v) auto v1, auto... v
  10. #else
  11. # define BOOST_LEAF_MATCH_ARGS(et,v1,v) typename leaf_detail::et::type v1, typename leaf_detail::et::type... v
  12. #endif
  13. #define BOOST_LEAF_ESC(...) __VA_ARGS__
  14. namespace boost { namespace leaf {
  15. namespace leaf_detail
  16. {
  17. #if __cplusplus >= 201703L
  18. template <class MatchType, class T>
  19. BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE bool cmp_value_pack( MatchType const & e, bool (*P)(T) noexcept ) noexcept
  20. {
  21. BOOST_LEAF_ASSERT(P != nullptr);
  22. return P(e);
  23. }
  24. template <class MatchType, class T>
  25. BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE bool cmp_value_pack( MatchType const & e, bool (*P)(T) )
  26. {
  27. BOOST_LEAF_ASSERT(P != nullptr);
  28. return P(e);
  29. }
  30. #endif
  31. template <class MatchType, class V>
  32. BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE bool cmp_value_pack( MatchType const & e, V v )
  33. {
  34. return e == v;
  35. }
  36. template <class MatchType, class VCar, class... VCdr>
  37. BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE bool cmp_value_pack( MatchType const & e, VCar car, VCdr ... cdr )
  38. {
  39. return cmp_value_pack(e, car) || cmp_value_pack(e, cdr...);
  40. }
  41. }
  42. ////////////////////////////////////////
  43. #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
  44. template <class E, class Enum = E>
  45. struct condition
  46. {
  47. static_assert(std::is_error_condition_enum<Enum>::value || std::is_error_code_enum<Enum>::value, "leaf::condition<E, Enum> requires Enum to be registered either with std::is_error_condition_enum or std::is_error_code_enum.");
  48. };
  49. template <class Enum>
  50. struct condition<Enum, Enum>
  51. {
  52. static_assert(std::is_error_condition_enum<Enum>::value || std::is_error_code_enum<Enum>::value, "leaf::condition<Enum> requires Enum to be registered either with std::is_error_condition_enum or std::is_error_code_enum.");
  53. };
  54. #if __cplusplus >= 201703L
  55. template <class ErrorCodeEnum>
  56. BOOST_LEAF_CONSTEXPR inline bool category( std::error_code const & ec )
  57. {
  58. static_assert(std::is_error_code_enum<ErrorCodeEnum>::value, "leaf::category requires an error code enum");
  59. return &ec.category() == &std::error_code(ErrorCodeEnum{}).category();
  60. }
  61. #endif
  62. #endif
  63. ////////////////////////////////////////
  64. namespace leaf_detail
  65. {
  66. template <class T>
  67. struct match_enum_type
  68. {
  69. using type = T;
  70. };
  71. #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
  72. template <class Enum>
  73. struct match_enum_type<condition<Enum, Enum>>
  74. {
  75. using type = Enum;
  76. };
  77. template <class E, class Enum>
  78. struct match_enum_type<condition<E, Enum>>
  79. {
  80. static_assert(sizeof(Enum) == 0, "leaf::condition<E, Enum> should be used with leaf::match_value<>, not with leaf::match<>");
  81. };
  82. #endif
  83. }
  84. template <class E, BOOST_LEAF_MATCH_ARGS(match_enum_type<E>, V1, V)>
  85. struct match
  86. {
  87. using error_type = E;
  88. E matched;
  89. template <class T>
  90. BOOST_LEAF_CONSTEXPR static bool evaluate(T && x)
  91. {
  92. return leaf_detail::cmp_value_pack(std::forward<T>(x), V1, V...);
  93. }
  94. };
  95. #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
  96. template <class Enum, BOOST_LEAF_MATCH_ARGS(BOOST_LEAF_ESC(match_enum_type<condition<Enum, Enum>>), V1, V)>
  97. struct match<condition<Enum, Enum>, V1, V...>
  98. {
  99. using error_type = std::error_code;
  100. std::error_code const & matched;
  101. BOOST_LEAF_CONSTEXPR static bool evaluate(std::error_code const & e) noexcept
  102. {
  103. return leaf_detail::cmp_value_pack(e, V1, V...);
  104. }
  105. };
  106. #endif
  107. template <class E, BOOST_LEAF_MATCH_ARGS(match_enum_type<E>, V1, V)>
  108. struct is_predicate<match<E, V1, V...>>: std::true_type
  109. {
  110. };
  111. ////////////////////////////////////////
  112. namespace leaf_detail
  113. {
  114. template <class E>
  115. struct match_value_enum_type
  116. {
  117. using type = typename std::remove_reference<decltype(std::declval<E>().value)>::type;
  118. };
  119. #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
  120. template <class E, class Enum>
  121. struct match_value_enum_type<condition<E, Enum>>
  122. {
  123. using type = Enum;
  124. };
  125. template <class Enum>
  126. struct match_value_enum_type<condition<Enum, Enum>>
  127. {
  128. static_assert(sizeof(Enum)==0, "leaf::condition<Enum> should be used with leaf::match<>, not with leaf::match_value<>");
  129. };
  130. #endif
  131. }
  132. template <class E, BOOST_LEAF_MATCH_ARGS(match_value_enum_type<E>, V1, V)>
  133. struct match_value
  134. {
  135. using error_type = E;
  136. E const & matched;
  137. BOOST_LEAF_CONSTEXPR static bool evaluate(E const & e) noexcept
  138. {
  139. return leaf_detail::cmp_value_pack(e.value, V1, V...);
  140. }
  141. };
  142. #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
  143. template <class E, class Enum, BOOST_LEAF_MATCH_ARGS(BOOST_LEAF_ESC(match_value_enum_type<condition<E, Enum>>), V1, V)>
  144. struct match_value<condition<E, Enum>, V1, V...>
  145. {
  146. using error_type = E;
  147. E const & matched;
  148. BOOST_LEAF_CONSTEXPR static bool evaluate(E const & e)
  149. {
  150. return leaf_detail::cmp_value_pack(e.value, V1, V...);
  151. }
  152. };
  153. #endif
  154. template <class E, BOOST_LEAF_MATCH_ARGS(match_value_enum_type<E>, V1, V)>
  155. struct is_predicate<match_value<E, V1, V...>>: std::true_type
  156. {
  157. };
  158. ////////////////////////////////////////
  159. #if __cplusplus >= 201703L
  160. template <auto, auto, auto...>
  161. struct match_member;
  162. template <class T, class E, T E::* P, auto V1, auto... V>
  163. struct match_member<P, V1, V...>
  164. {
  165. using error_type = E;
  166. E const & matched;
  167. BOOST_LEAF_CONSTEXPR static bool evaluate(E const & e) noexcept
  168. {
  169. return leaf_detail::cmp_value_pack(e.*P, V1, V...);
  170. }
  171. };
  172. template <auto P, auto V1, auto... V>
  173. struct is_predicate<match_member<P, V1, V...>>: std::true_type
  174. {
  175. };
  176. #endif
  177. ////////////////////////////////////////
  178. template <class P>
  179. struct if_not
  180. {
  181. using error_type = typename P::error_type;
  182. decltype(std::declval<P>().matched) matched;
  183. template <class E>
  184. BOOST_LEAF_CONSTEXPR static bool evaluate(E && e) noexcept
  185. {
  186. return !P::evaluate(std::forward<E>(e));
  187. }
  188. };
  189. template <class P>
  190. struct is_predicate<if_not<P>>: std::true_type
  191. {
  192. };
  193. ////////////////////////////////////////
  194. #ifndef BOOST_LEAF_NO_EXCEPTIONS
  195. namespace leaf_detail
  196. {
  197. template <class Ex>
  198. BOOST_LEAF_CONSTEXPR inline bool check_exception_pack( std::exception const & ex, Ex const * ) noexcept
  199. {
  200. return dynamic_cast<Ex const *>(&ex)!=nullptr;
  201. }
  202. template <class Ex, class... ExRest>
  203. BOOST_LEAF_CONSTEXPR inline bool check_exception_pack( std::exception const & ex, Ex const *, ExRest const * ... ex_rest ) noexcept
  204. {
  205. return dynamic_cast<Ex const *>(&ex)!=nullptr || check_exception_pack(ex, ex_rest...);
  206. }
  207. BOOST_LEAF_CONSTEXPR inline bool check_exception_pack( std::exception const & ) noexcept
  208. {
  209. return true;
  210. }
  211. }
  212. template <class... Ex>
  213. struct catch_
  214. {
  215. using error_type = void;
  216. std::exception const & matched;
  217. BOOST_LEAF_CONSTEXPR static bool evaluate(std::exception const & ex) noexcept
  218. {
  219. return leaf_detail::check_exception_pack(ex, static_cast<Ex const *>(nullptr)...);
  220. }
  221. };
  222. template <class Ex>
  223. struct catch_<Ex>
  224. {
  225. using error_type = void;
  226. Ex const & matched;
  227. BOOST_LEAF_CONSTEXPR static Ex const * evaluate(std::exception const & ex) noexcept
  228. {
  229. return dynamic_cast<Ex const *>(&ex);
  230. }
  231. explicit catch_( std::exception const & ex ):
  232. matched(*dynamic_cast<Ex const *>(&ex))
  233. {
  234. }
  235. };
  236. template <class... Ex>
  237. struct is_predicate<catch_<Ex...>>: std::true_type
  238. {
  239. };
  240. #endif
  241. } }
  242. #endif