Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-17 08:52:03

0001 // Copyright (c) 2018-2025 Jean-Louis Leroy
0002 // Distributed under the Boost Software License, Version 1.0.
0003 // See accompanying file LICENSE_1_0.txt
0004 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 #ifndef BOOST_OPENMETHOD_POLICY_VECTORED_ERROR_HPP
0007 #define BOOST_OPENMETHOD_POLICY_VECTORED_ERROR_HPP
0008 
0009 #include <boost/openmethod/preamble.hpp>
0010 
0011 #include <functional>
0012 #include <variant>
0013 
0014 namespace boost::openmethod::policies {
0015 
0016 //! Calls a std::function with the error.
0017 //!
0018 //! Wraps the error in a @ref std::variant, and calls a `std::function` with it.
0019 //! The function object is initialized to a function (@ref default_handler) that
0020 //! writes a description of the error, using the @ref output policy, if it is
0021 //! available in the registry.
0022 //!
0023 //! This is the error handler used by the default registry. In debug variants,
0024 //! it writes an error message to `stderr`, then returns. In release variants,
0025 //! no message is emitted. Any call by the library to the error policy is
0026 //! immediately followed by a call to @ref abort.
0027 //!
0028 //! By default, the library is exception-agnostic: it is exception-safe, but it
0029 //! does not throw exceptions by itself. The program may replace the default
0030 //! handler with a function that throws an exception, possibly preventing
0031 //! program termination. The @ref throw_error_handler policy can also be used to
0032 //! enable exception throwing on a registry basis.
0033 
0034 struct default_error_handler : error_handler {
0035     //! A ErrorHandlerFn metafunction.
0036     //!
0037     //! @tparam Registry The registry containing this policy.
0038     template<class Registry>
0039     class fn {
0040         template<typename, typename, typename>
0041         struct error_variant_aux;
0042 
0043         template<
0044             typename T, class... Errors, class Policy, class... MorePolicies>
0045         struct error_variant_aux<
0046             T, std::variant<Errors...>, mp11::mp_list<Policy, MorePolicies...>>
0047             : error_variant_aux<
0048                   void, std::variant<Errors...>,
0049                   mp11::mp_list<MorePolicies...>> {};
0050 
0051         template<class... Errors, class Policy, class... MorePolicies>
0052         struct error_variant_aux<
0053             std::void_t<typename Policy::errors>, std::variant<Errors...>,
0054             mp11::mp_list<Policy, MorePolicies...>>
0055             : error_variant_aux<
0056                   void,
0057                   mp11::mp_append<
0058                       std::variant<Errors...>, typename Policy::errors>,
0059                   mp11::mp_list<MorePolicies...>> {};
0060 
0061         template<class... Errors>
0062         struct error_variant_aux<
0063             void, std::variant<Errors...>, mp11::mp_list<>> {
0064             using type = std::variant<Errors...>;
0065         };
0066 
0067       public:
0068         //! A @ref std::variant containing an instance of a subclass of @ref
0069         //! openmethod_error.
0070         using error_variant = typename error_variant_aux<
0071             void,
0072             std::variant<
0073                 not_initialized, no_overrider, ambiguous_call, missing_class,
0074                 missing_base, odr_violation, final_error>,
0075             typename Registry::policy_list>::type;
0076 
0077         //! The type of the error handler function object.
0078         using function_type = std::function<void(const error_variant& error)>;
0079 
0080         //! Calls a function with the error object, wrapped in an @ref
0081         //! error_variant.
0082         //!
0083         //! @tparam Error A subclass of @ref openmethod_error.
0084         //! @param error The error object.
0085         template<class Error>
0086         static auto error(const Error& error) -> void {
0087             handler(error_variant(error));
0088         }
0089 
0090         //! Sets the function to be called to handle errors.
0091         //!
0092         //! Sets the error handler function to a new value, and returns the
0093         //! previous function.
0094         //!
0095         //! @param new_handler the new function.
0096         //! @return The previous function.
0097         static auto set(function_type new_handler) -> function_type {
0098             auto prev = handler;
0099             handler = std::move(new_handler);
0100 
0101             return prev;
0102         }
0103 
0104         //! The default error handler function.
0105         //!
0106         //! @param error A variant containing the error.
0107         //!
0108         //! If `Registry` contains an @ref output policy, writes a description
0109         //! of the error; otherwise, does nothing.
0110         static auto default_handler(const error_variant& error) -> void {
0111             if constexpr (Registry::has_output) {
0112                 std::visit(
0113                     [](auto&& error) {
0114                         error.template write<Registry>(Registry::output::os);
0115                     },
0116                     error);
0117                 Registry::output::os << "\n";
0118             }
0119         }
0120 
0121       private:
0122         static function_type handler;
0123     };
0124 };
0125 
0126 template<class Registry>
0127 typename default_error_handler::fn<Registry>::function_type
0128     default_error_handler::fn<Registry>::handler = default_handler;
0129 
0130 } // namespace boost::openmethod::policies
0131 
0132 #endif