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