pred.hpp 7.8 KB

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