diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 09624ce..b8d0a83 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -55,9 +55,9 @@ add_executable(core_api core_api.cpp) target_link_libraries(core_api Boost::openmethod) add_test(NAME core_api COMMAND core_api) -add_executable(vectored_error_handler vectored_error_handler.cpp) -target_link_libraries(vectored_error_handler Boost::openmethod) -add_test(NAME vectored_error_handler COMMAND vectored_error_handler) +add_executable(default_error_handler default_error_handler.cpp) +target_link_libraries(default_error_handler Boost::openmethod) +add_test(NAME default_error_handler COMMAND default_error_handler) add_executable(throw_error_handler throw_error_handler.cpp) target_link_libraries(throw_error_handler Boost::openmethod) diff --git a/examples/vectored_error_handler.cpp b/examples/default_error_handler.cpp similarity index 100% rename from examples/vectored_error_handler.cpp rename to examples/default_error_handler.cpp diff --git a/include/boost/openmethod/default_registry.hpp b/include/boost/openmethod/default_registry.hpp index 9a5a0a5..83ccc2b 100644 --- a/include/boost/openmethod/default_registry.hpp +++ b/include/boost/openmethod/default_registry.hpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include namespace boost::openmethod { @@ -19,11 +19,11 @@ namespace policies { struct release : registry< std_rtti, fast_perfect_hash, vptr_vector, - vectored_error_handler, stderr_output> {}; + default_error_handler, stderr_output> {}; struct debug : registry< - std_rtti, fast_perfect_hash, vptr_vector, vectored_error_handler, + std_rtti, fast_perfect_hash, vptr_vector, default_error_handler, runtime_checks, stderr_output, trace> {}; } // namespace policies diff --git a/include/boost/openmethod/policies/default_error_handler.hpp b/include/boost/openmethod/policies/default_error_handler.hpp new file mode 100644 index 0000000..b241dd5 --- /dev/null +++ b/include/boost/openmethod/policies/default_error_handler.hpp @@ -0,0 +1,95 @@ +// Copyright (c) 2018-2025 Jean-Louis Leroy +// 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) + +#ifndef BOOST_OPENMETHOD_POLICY_VECTORED_ERROR_HPP +#define BOOST_OPENMETHOD_POLICY_VECTORED_ERROR_HPP + +#include + +#include +#include + +namespace boost::openmethod::policies { + +struct default_error_handler : error_handler { + using error_variant = std::variant< + openmethod_error, not_implemented_error, unknown_class_error, + hash_search_error, type_mismatch_error, static_slot_error, + static_stride_error>; + + using function_type = std::function; + + template + class fn { + public: + template + static auto error(const Error& error) -> void { + handler(error_variant(error)); + } + + static auto set(function_type handler) -> function_type { + auto prev = handler; + fn::handler = handler; + + return prev; + } + + static auto default_handler(const error_variant& error_v) { + using namespace detail; + using namespace policies; + + if constexpr (Registry::template has_policy) { + auto& os = Registry::template policy::os; + + if (auto error = std::get_if(&error_v)) { + os << "no applicable overrider for "; + Registry::template policy::type_name( + error->method, os); + os << "("; + auto comma = ""; + + for (auto ti : + range{error->types, error->types + error->arity}) { + os << comma; + Registry::template policy::type_name( + ti, os); + comma = ", "; + } + + os << ")\n"; + } else if ( + auto error = std::get_if(&error_v)) { + os << "unknown class "; + Registry::template policy::type_name( + error->type, os); + os << "\n"; + } else if ( + auto error = std::get_if(&error_v)) { + os << "invalid method table for "; + Registry::template policy::type_name( + error->type, os); + os << "\n"; + } else if ( + auto error = std::get_if(&error_v)) { + os << "could not find hash factors after " + << error->attempts << "s using " << error->buckets + << " buckets\n"; + } + } + } + + private: + static function_type + handler; // Cannot be inline static because it confuses MSVC + }; +}; + +template +typename default_error_handler::function_type + default_error_handler::fn::handler = default_handler; + +} // namespace boost::openmethod::policies + +#endif diff --git a/include/boost/openmethod/policies/vectored_error_handler.hpp b/include/boost/openmethod/policies/vectored_error_handler.hpp index 583fa9a..b241dd5 100644 --- a/include/boost/openmethod/policies/vectored_error_handler.hpp +++ b/include/boost/openmethod/policies/vectored_error_handler.hpp @@ -13,7 +13,7 @@ namespace boost::openmethod::policies { -struct vectored_error_handler : error_handler { +struct default_error_handler : error_handler { using error_variant = std::variant< openmethod_error, not_implemented_error, unknown_class_error, hash_search_error, type_mismatch_error, static_slot_error, @@ -87,8 +87,8 @@ struct vectored_error_handler : error_handler { }; template -typename vectored_error_handler::function_type - vectored_error_handler::fn::handler = default_handler; +typename default_error_handler::function_type + default_error_handler::fn::handler = default_handler; } // namespace boost::openmethod::policies diff --git a/test/test_blackbox.cpp b/test/test_blackbox.cpp index c57fbd1..8962649 100644 --- a/test/test_blackbox.cpp +++ b/test/test_blackbox.cpp @@ -523,7 +523,7 @@ BOOST_OPENMETHOD_OVERRIDE( } void test_handler( - const policies::vectored_error_handler::error_variant& error_v) { + const policies::default_error_handler::error_variant& error_v) { if (auto error = std::get_if(&error_v)) { throw *error; }