123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- #ifndef BOOST_LEAF_PRED_HPP_INCLUDED
- #define BOOST_LEAF_PRED_HPP_INCLUDED
- // Copyright 2018-2023 Emil Dotchevski and Reverge Studios, Inc.
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- #include <boost/leaf/config.hpp>
- #include <boost/leaf/handle_errors.hpp>
- #if __cplusplus >= 201703L
- # define BOOST_LEAF_MATCH_ARGS(et,v1,v) auto v1, auto... v
- #else
- # define BOOST_LEAF_MATCH_ARGS(et,v1,v) typename leaf_detail::et::type v1, typename leaf_detail::et::type... v
- #endif
- #define BOOST_LEAF_ESC(...) __VA_ARGS__
- namespace boost { namespace leaf {
- namespace leaf_detail
- {
- #if __cplusplus >= 201703L
- template <class MatchType, class T>
- BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE bool cmp_value_pack( MatchType const & e, bool (*P)(T) noexcept ) noexcept
- {
- BOOST_LEAF_ASSERT(P != nullptr);
- return P(e);
- }
- template <class MatchType, class T>
- BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE bool cmp_value_pack( MatchType const & e, bool (*P)(T) )
- {
- BOOST_LEAF_ASSERT(P != nullptr);
- return P(e);
- }
- #endif
- template <class MatchType, class V>
- BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE bool cmp_value_pack( MatchType const & e, V v )
- {
- return e == v;
- }
- template <class MatchType, class VCar, class... VCdr>
- BOOST_LEAF_CONSTEXPR BOOST_LEAF_ALWAYS_INLINE bool cmp_value_pack( MatchType const & e, VCar car, VCdr ... cdr )
- {
- return cmp_value_pack(e, car) || cmp_value_pack(e, cdr...);
- }
- }
- ////////////////////////////////////////
- #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
- template <class E, class Enum = E>
- struct condition
- {
- 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.");
- };
- template <class Enum>
- struct condition<Enum, Enum>
- {
- 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.");
- };
- #if __cplusplus >= 201703L
- template <class ErrorCodeEnum>
- BOOST_LEAF_CONSTEXPR inline bool category( std::error_code const & ec )
- {
- static_assert(std::is_error_code_enum<ErrorCodeEnum>::value, "leaf::category requires an error code enum");
- return &ec.category() == &std::error_code(ErrorCodeEnum{}).category();
- }
- #endif
- #endif
- ////////////////////////////////////////
- namespace leaf_detail
- {
- template <class T>
- struct match_enum_type
- {
- using type = T;
- };
- #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
- template <class Enum>
- struct match_enum_type<condition<Enum, Enum>>
- {
- using type = Enum;
- };
- template <class E, class Enum>
- struct match_enum_type<condition<E, Enum>>
- {
- static_assert(sizeof(Enum) == 0, "leaf::condition<E, Enum> should be used with leaf::match_value<>, not with leaf::match<>");
- };
- #endif
- }
- template <class E, BOOST_LEAF_MATCH_ARGS(match_enum_type<E>, V1, V)>
- struct match
- {
- using error_type = E;
- E matched;
- template <class T>
- BOOST_LEAF_CONSTEXPR static bool evaluate(T && x)
- {
- return leaf_detail::cmp_value_pack(std::forward<T>(x), V1, V...);
- }
- };
- #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
- template <class Enum, BOOST_LEAF_MATCH_ARGS(BOOST_LEAF_ESC(match_enum_type<condition<Enum, Enum>>), V1, V)>
- struct match<condition<Enum, Enum>, V1, V...>
- {
- using error_type = std::error_code;
- std::error_code const & matched;
- BOOST_LEAF_CONSTEXPR static bool evaluate(std::error_code const & e) noexcept
- {
- return leaf_detail::cmp_value_pack(e, V1, V...);
- }
- };
- #endif
- template <class E, BOOST_LEAF_MATCH_ARGS(match_enum_type<E>, V1, V)>
- struct is_predicate<match<E, V1, V...>>: std::true_type
- {
- };
- ////////////////////////////////////////
- namespace leaf_detail
- {
- template <class E>
- struct match_value_enum_type
- {
- using type = typename std::remove_reference<decltype(std::declval<E>().value)>::type;
- };
- #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
- template <class E, class Enum>
- struct match_value_enum_type<condition<E, Enum>>
- {
- using type = Enum;
- };
- template <class Enum>
- struct match_value_enum_type<condition<Enum, Enum>>
- {
- static_assert(sizeof(Enum)==0, "leaf::condition<Enum> should be used with leaf::match<>, not with leaf::match_value<>");
- };
- #endif
- }
- template <class E, BOOST_LEAF_MATCH_ARGS(match_value_enum_type<E>, V1, V)>
- struct match_value
- {
- using error_type = E;
- E const & matched;
- BOOST_LEAF_CONSTEXPR static bool evaluate(E const & e) noexcept
- {
- return leaf_detail::cmp_value_pack(e.value, V1, V...);
- }
- };
- #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR
- template <class E, class Enum, BOOST_LEAF_MATCH_ARGS(BOOST_LEAF_ESC(match_value_enum_type<condition<E, Enum>>), V1, V)>
- struct match_value<condition<E, Enum>, V1, V...>
- {
- using error_type = E;
- E const & matched;
- BOOST_LEAF_CONSTEXPR static bool evaluate(E const & e)
- {
- return leaf_detail::cmp_value_pack(e.value, V1, V...);
- }
- };
- #endif
- template <class E, BOOST_LEAF_MATCH_ARGS(match_value_enum_type<E>, V1, V)>
- struct is_predicate<match_value<E, V1, V...>>: std::true_type
- {
- };
- ////////////////////////////////////////
- #if __cplusplus >= 201703L
- template <auto, auto, auto...>
- struct match_member;
- template <class T, class E, T E::* P, auto V1, auto... V>
- struct match_member<P, V1, V...>
- {
- using error_type = E;
- E const & matched;
- BOOST_LEAF_CONSTEXPR static bool evaluate(E const & e) noexcept
- {
- return leaf_detail::cmp_value_pack(e.*P, V1, V...);
- }
- };
- template <auto P, auto V1, auto... V>
- struct is_predicate<match_member<P, V1, V...>>: std::true_type
- {
- };
- #endif
- ////////////////////////////////////////
- template <class P>
- struct if_not
- {
- using error_type = typename P::error_type;
- decltype(std::declval<P>().matched) matched;
- template <class E>
- BOOST_LEAF_CONSTEXPR static bool evaluate(E && e) noexcept
- {
- return !P::evaluate(std::forward<E>(e));
- }
- };
- template <class P>
- struct is_predicate<if_not<P>>: std::true_type
- {
- };
- ////////////////////////////////////////
- #ifndef BOOST_LEAF_NO_EXCEPTIONS
- namespace leaf_detail
- {
- template <class Ex>
- BOOST_LEAF_CONSTEXPR inline bool check_exception_pack( std::exception const & ex, Ex const * ) noexcept
- {
- return dynamic_cast<Ex const *>(&ex)!=nullptr;
- }
- template <class Ex, class... ExRest>
- BOOST_LEAF_CONSTEXPR inline bool check_exception_pack( std::exception const & ex, Ex const *, ExRest const * ... ex_rest ) noexcept
- {
- return dynamic_cast<Ex const *>(&ex)!=nullptr || check_exception_pack(ex, ex_rest...);
- }
- BOOST_LEAF_CONSTEXPR inline bool check_exception_pack( std::exception const & ) noexcept
- {
- return true;
- }
- }
- template <class... Ex>
- struct catch_
- {
- using error_type = void;
- std::exception const & matched;
- BOOST_LEAF_CONSTEXPR static bool evaluate(std::exception const & ex) noexcept
- {
- return leaf_detail::check_exception_pack(ex, static_cast<Ex const *>(nullptr)...);
- }
- };
- template <class Ex>
- struct catch_<Ex>
- {
- using error_type = void;
- Ex const & matched;
- BOOST_LEAF_CONSTEXPR static Ex const * evaluate(std::exception const & ex) noexcept
- {
- return dynamic_cast<Ex const *>(&ex);
- }
- explicit catch_( std::exception const & ex ):
- matched(*dynamic_cast<Ex const *>(&ex))
- {
- }
- };
- template <class... Ex>
- struct is_predicate<catch_<Ex...>>: std::true_type
- {
- };
- #endif
- } }
- #endif
|