File indexing completed on 2025-01-18 09:39:13
0001 #ifndef BOOST_LEAF_PRED_HPP_INCLUDED
0002 #define BOOST_LEAF_PRED_HPP_INCLUDED
0003
0004
0005
0006
0007
0008
0009 #include <boost/leaf/config.hpp>
0010 #include <boost/leaf/handle_errors.hpp>
0011
0012 #if __cplusplus >= 201703L
0013 # define BOOST_LEAF_MATCH_ARGS(et,v1,v) auto v1, auto... v
0014 #else
0015 # define BOOST_LEAF_MATCH_ARGS(et,v1,v) typename leaf_detail::et::type v1, typename leaf_detail::et::type... v
0016 #endif
0017 #define BOOST_LEAF_ESC(...) __VA_ARGS__
0018
0019 namespace boost { namespace leaf {
0020
0021 namespace leaf_detail
0022 {
0023 #if __cplusplus >= 201703L
0024 template <class MatchType, class T>
0025 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE bool cmp_value_pack( MatchType const & e, bool (*P)(T) noexcept ) noexcept
0026 {
0027 BOOST_LEAF_ASSERT(P != nullptr);
0028 return P(e);
0029 }
0030
0031 template <class MatchType, class T>
0032 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE bool cmp_value_pack( MatchType const & e, bool (*P)(T) )
0033 {
0034 BOOST_LEAF_ASSERT(P != nullptr);
0035 return P(e);
0036 }
0037 #endif
0038
0039 template <class MatchType, class V>
0040 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE bool cmp_value_pack( MatchType const & e, V v )
0041 {
0042 return e == v;
0043 }
0044
0045 template <class MatchType, class VCar, class... VCdr>
0046 BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE bool cmp_value_pack( MatchType const & e, VCar car, VCdr ... cdr )
0047 {
0048 return cmp_value_pack(e, car) || cmp_value_pack(e, cdr...);
0049 }
0050 }
0051
0052
0053
0054 #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
0055 template <class E, class Enum = E>
0056 struct condition
0057 {
0058 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.");
0059 };
0060
0061 template <class Enum>
0062 struct condition<Enum, Enum>
0063 {
0064 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.");
0065 };
0066
0067 #if __cplusplus >= 201703L
0068 template <class ErrorCodeEnum>
0069 BOOST_LEAF_CONSTEXPR inline bool category( std::error_code const & ec )
0070 {
0071 static_assert(std::is_error_code_enum<ErrorCodeEnum>::value, "leaf::category requires an error code enum");
0072 return &ec.category() == &std::error_code(ErrorCodeEnum{}).category();
0073 }
0074 #endif
0075 #endif
0076
0077
0078
0079 namespace leaf_detail
0080 {
0081 template <class T>
0082 struct match_enum_type
0083 {
0084 using type = T;
0085 };
0086
0087 #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
0088 template <class Enum>
0089 struct match_enum_type<condition<Enum, Enum>>
0090 {
0091 using type = Enum;
0092 };
0093
0094 template <class E, class Enum>
0095 struct match_enum_type<condition<E, Enum>>
0096 {
0097 static_assert(sizeof(Enum) == 0, "leaf::condition<E, Enum> should be used with leaf::match_value<>, not with leaf::match<>");
0098 };
0099 #endif
0100 }
0101
0102 template <class E, BOOST_LEAF_MATCH_ARGS(match_enum_type<E>, V1, V)>
0103 struct match
0104 {
0105 using error_type = E;
0106 E matched;
0107
0108 template <class T>
0109 BOOST_LEAF_CONSTEXPR static bool evaluate(T && x)
0110 {
0111 return leaf_detail::cmp_value_pack(std::forward<T>(x), V1, V...);
0112 }
0113 };
0114
0115 #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
0116 template <class Enum, BOOST_LEAF_MATCH_ARGS(BOOST_LEAF_ESC(match_enum_type<condition<Enum, Enum>>), V1, V)>
0117 struct match<condition<Enum, Enum>, V1, V...>
0118 {
0119 using error_type = std::error_code;
0120 std::error_code const & matched;
0121
0122 BOOST_LEAF_CONSTEXPR static bool evaluate(std::error_code const & e) noexcept
0123 {
0124 return leaf_detail::cmp_value_pack(e, V1, V...);
0125 }
0126 };
0127 #endif
0128
0129 template <class E, BOOST_LEAF_MATCH_ARGS(match_enum_type<E>, V1, V)>
0130 struct is_predicate<match<E, V1, V...>>: std::true_type
0131 {
0132 };
0133
0134
0135
0136 namespace leaf_detail
0137 {
0138 template <class E>
0139 struct match_value_enum_type
0140 {
0141 using type = typename std::remove_reference<decltype(std::declval<E>().value)>::type;
0142 };
0143
0144 #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
0145 template <class E, class Enum>
0146 struct match_value_enum_type<condition<E, Enum>>
0147 {
0148 using type = Enum;
0149 };
0150
0151 template <class Enum>
0152 struct match_value_enum_type<condition<Enum, Enum>>
0153 {
0154 static_assert(sizeof(Enum)==0, "leaf::condition<Enum> should be used with leaf::match<>, not with leaf::match_value<>");
0155 };
0156 #endif
0157 }
0158
0159 template <class E, BOOST_LEAF_MATCH_ARGS(match_value_enum_type<E>, V1, V)>
0160 struct match_value
0161 {
0162 using error_type = E;
0163 E const & matched;
0164
0165 BOOST_LEAF_CONSTEXPR static bool evaluate(E const & e) noexcept
0166 {
0167 return leaf_detail::cmp_value_pack(e.value, V1, V...);
0168 }
0169 };
0170
0171 #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
0172 template <class E, class Enum, BOOST_LEAF_MATCH_ARGS(BOOST_LEAF_ESC(match_value_enum_type<condition<E, Enum>>), V1, V)>
0173 struct match_value<condition<E, Enum>, V1, V...>
0174 {
0175 using error_type = E;
0176 E const & matched;
0177
0178 BOOST_LEAF_CONSTEXPR static bool evaluate(E const & e)
0179 {
0180 return leaf_detail::cmp_value_pack(e.value, V1, V...);
0181 }
0182 };
0183 #endif
0184
0185 template <class E, BOOST_LEAF_MATCH_ARGS(match_value_enum_type<E>, V1, V)>
0186 struct is_predicate<match_value<E, V1, V...>>: std::true_type
0187 {
0188 };
0189
0190
0191
0192 #if __cplusplus >= 201703L
0193 template <auto, auto, auto...>
0194 struct match_member;
0195
0196 template <class T, class E, T E::* P, auto V1, auto... V>
0197 struct match_member<P, V1, V...>
0198 {
0199 using error_type = E;
0200 E const & matched;
0201
0202 BOOST_LEAF_CONSTEXPR static bool evaluate(E const & e) noexcept
0203 {
0204 return leaf_detail::cmp_value_pack(e.*P, V1, V...);
0205 }
0206 };
0207
0208 template <auto P, auto V1, auto... V>
0209 struct is_predicate<match_member<P, V1, V...>>: std::true_type
0210 {
0211 };
0212 #endif
0213
0214
0215
0216 template <class P>
0217 struct if_not
0218 {
0219 using error_type = typename P::error_type;
0220 decltype(std::declval<P>().matched) matched;
0221
0222 template <class E>
0223 BOOST_LEAF_CONSTEXPR static bool evaluate(E && e) noexcept
0224 {
0225 return !P::evaluate(std::forward<E>(e));
0226 }
0227 };
0228
0229 template <class P>
0230 struct is_predicate<if_not<P>>: std::true_type
0231 {
0232 };
0233
0234
0235
0236
0237 #ifndef BOOST_LEAF_NO_EXCEPTIONS
0238
0239 namespace leaf_detail
0240 {
0241 template <class Ex>
0242 BOOST_LEAF_CONSTEXPR inline bool check_exception_pack( std::exception const & ex, Ex const * ) noexcept
0243 {
0244 return dynamic_cast<Ex const *>(&ex)!=nullptr;
0245 }
0246
0247 template <class Ex, class... ExRest>
0248 BOOST_LEAF_CONSTEXPR inline bool check_exception_pack( std::exception const & ex, Ex const *, ExRest const * ... ex_rest ) noexcept
0249 {
0250 return dynamic_cast<Ex const *>(&ex)!=nullptr || check_exception_pack(ex, ex_rest...);
0251 }
0252
0253 BOOST_LEAF_CONSTEXPR inline bool check_exception_pack( std::exception const & ) noexcept
0254 {
0255 return true;
0256 }
0257 }
0258
0259 template <class... Ex>
0260 struct catch_
0261 {
0262 using error_type = void;
0263 std::exception const & matched;
0264
0265 BOOST_LEAF_CONSTEXPR static bool evaluate(std::exception const & ex) noexcept
0266 {
0267 return leaf_detail::check_exception_pack(ex, static_cast<Ex const *>(nullptr)...);
0268 }
0269 };
0270
0271 template <class Ex>
0272 struct catch_<Ex>
0273 {
0274 using error_type = void;
0275 Ex const & matched;
0276
0277 BOOST_LEAF_CONSTEXPR static Ex const * evaluate(std::exception const & ex) noexcept
0278 {
0279 return dynamic_cast<Ex const *>(&ex);
0280 }
0281
0282 explicit catch_( std::exception const & ex ):
0283 matched(*dynamic_cast<Ex const *>(&ex))
0284 {
0285 }
0286 };
0287
0288 template <class... Ex>
0289 struct is_predicate<catch_<Ex...>>: std::true_type
0290 {
0291 };
0292
0293 #endif
0294
0295 } }
0296
0297 #endif