From 57a031ae7a9eeb92d40e4d6245b9e689f5d87ee7 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 10 Jan 2023 18:27:01 +0700 Subject: [PATCH] little exception safety fixes --- develop/singles/headers/meta.hpp/meta_all.hpp | 69 ++++++++++--------- headers/meta.hpp/meta_base.hpp | 2 +- headers/meta.hpp/meta_base/base.hpp | 10 +++ headers/meta.hpp/meta_binds/class_bind.hpp | 19 +++-- .../meta.hpp/meta_detail/type_registry.hpp | 9 ++- headers/meta.hpp/meta_registry.hpp | 2 +- headers/meta.hpp/meta_states/constructor.hpp | 9 +-- headers/meta.hpp/meta_states/function.hpp | 9 +-- headers/meta.hpp/meta_states/method.hpp | 9 +-- 9 files changed, 74 insertions(+), 64 deletions(-) diff --git a/develop/singles/headers/meta.hpp/meta_all.hpp b/develop/singles/headers/meta.hpp/meta_all.hpp index 5b77de5..9cb91aa 100644 --- a/develop/singles/headers/meta.hpp/meta_all.hpp +++ b/develop/singles/headers/meta.hpp/meta_all.hpp @@ -39,6 +39,16 @@ # define META_HPP_NO_RTTI #endif +#if defined(META_HPP_NO_EXCEPTIONS) +# define META_HPP_TRY if ( true ) +# define META_HPP_CATCH(e) if ( false ) +# define META_HPP_RETHROW() std::abort() +#else +# define META_HPP_TRY try +# define META_HPP_CATCH(e) catch(e) +# define META_HPP_RETHROW() throw +#endif + namespace meta_hpp::detail { template < typename Enum > @@ -833,7 +843,7 @@ namespace meta_hpp namespace detail { inline void throw_exception_with [[noreturn]] (const char* what) { - #ifndef META_HPP_NO_EXCEPTIONS + #if !defined(META_HPP_NO_EXCEPTIONS) throw ::meta_hpp::exception(what); #else (void)what; @@ -3221,8 +3231,13 @@ namespace meta_hpp::detail std::call_once(init_flag, [this, &type_data](){ const locker lock; type_by_id_.emplace(type_data.id, any_type{&type_data}); - #ifndef META_HPP_NO_RTTI - type_by_rtti_.emplace(typeid(Type), any_type{&type_data}); + #if !defined(META_HPP_NO_RTTI) + META_HPP_TRY { + type_by_rtti_.emplace(typeid(Type), any_type{&type_data}); + } META_HPP_CATCH(...) { + type_by_id_.erase(type_data.id); + META_HPP_RETHROW(); + } #endif }); } @@ -3755,7 +3770,7 @@ namespace meta_hpp { template < typename T > [[nodiscard]] any_type resolve_polymorphic_type(T&& v) noexcept { - #ifndef META_HPP_NO_RTTI + #if !defined(META_HPP_NO_RTTI) using namespace detail; type_registry& registry = type_registry::instance(); return registry.get_type_by_rtti(typeid(v)); @@ -3814,16 +3829,21 @@ namespace meta_hpp requires detail::class_bind_base_kind { const class_type base_type = resolve_type(); - if ( data_->bases.contains(base_type) ) { + + if ( auto&& [_, success] = data_->bases.emplace(base_type); !success ) { return *this; } - data_->bases.emplace(base_type); - data_->bases_info.emplace(base_type, detail::class_type_data::base_info{ - .upcast = +[](void* derived) -> void* { - return static_cast(static_cast(derived)); - } - }); + META_HPP_TRY { + data_->bases_info.emplace(base_type, detail::class_type_data::base_info{ + .upcast = +[](void* derived) -> void* { + return static_cast(static_cast(derived)); + } + }); + } META_HPP_CATCH(...) { + data_->bases.erase(base_type); + META_HPP_RETHROW(); + } return *this; } @@ -5309,18 +5329,13 @@ namespace meta_hpp::detail using ct = constructor_traits; using ct_argument_types = typename ct::argument_types; - argument_list arguments; - arguments.reserve(ct::arity); - - [&arguments](std::index_sequence) mutable { + return [](std::index_sequence){ [[maybe_unused]] const auto make_argument = [](std::index_sequence){ using P = type_list_at_t; return argument{argument_state::make

(I, metadata_map{})}; }; - (arguments.push_back(make_argument(std::index_sequence{})), ...); + return argument_list{make_argument(std::index_sequence{})...}; }(std::make_index_sequence()); - - return arguments; } } @@ -5831,18 +5846,13 @@ namespace meta_hpp::detail using ft = function_traits; using ft_argument_types = typename ft::argument_types; - argument_list arguments; - arguments.reserve(ft::arity); - - [&arguments](std::index_sequence) mutable { + return [](std::index_sequence){ [[maybe_unused]] const auto make_argument = [](std::index_sequence){ using P = type_list_at_t; return argument{argument_state::make

(I, metadata_map{})}; }; - (arguments.push_back(make_argument(std::index_sequence{})), ...); + return argument_list{make_argument(std::index_sequence{})...}; }(std::make_index_sequence()); - - return arguments; } } @@ -6609,18 +6619,13 @@ namespace meta_hpp::detail using mt = method_traits; using mt_argument_types = typename mt::argument_types; - argument_list arguments; - arguments.reserve(mt::arity); - - [&arguments](std::index_sequence) mutable { + return [](std::index_sequence){ [[maybe_unused]] const auto make_argument = [](std::index_sequence){ using P = type_list_at_t; return argument{argument_state::make

(I, metadata_map{})}; }; - (arguments.push_back(make_argument(std::index_sequence{})), ...); + return argument_list{make_argument(std::index_sequence{})...}; }(std::make_index_sequence()); - - return arguments; } } diff --git a/headers/meta.hpp/meta_base.hpp b/headers/meta.hpp/meta_base.hpp index b92e47c..c976a40 100644 --- a/headers/meta.hpp/meta_base.hpp +++ b/headers/meta.hpp/meta_base.hpp @@ -46,7 +46,7 @@ namespace meta_hpp namespace detail { inline void throw_exception_with [[noreturn]] (const char* what) { - #ifndef META_HPP_NO_EXCEPTIONS + #if !defined(META_HPP_NO_EXCEPTIONS) throw ::meta_hpp::exception(what); #else (void)what; diff --git a/headers/meta.hpp/meta_base/base.hpp b/headers/meta.hpp/meta_base/base.hpp index 887ddf8..47bf880 100644 --- a/headers/meta.hpp/meta_base/base.hpp +++ b/headers/meta.hpp/meta_base/base.hpp @@ -41,3 +41,13 @@ #if !defined(__cpp_rtti) # define META_HPP_NO_RTTI #endif + +#if defined(META_HPP_NO_EXCEPTIONS) +# define META_HPP_TRY if ( true ) +# define META_HPP_CATCH(e) if ( false ) +# define META_HPP_RETHROW() std::abort() +#else +# define META_HPP_TRY try +# define META_HPP_CATCH(e) catch(e) +# define META_HPP_RETHROW() throw +#endif diff --git a/headers/meta.hpp/meta_binds/class_bind.hpp b/headers/meta.hpp/meta_binds/class_bind.hpp index 6a3e96c..5bb3077 100644 --- a/headers/meta.hpp/meta_binds/class_bind.hpp +++ b/headers/meta.hpp/meta_binds/class_bind.hpp @@ -34,16 +34,21 @@ namespace meta_hpp requires detail::class_bind_base_kind { const class_type base_type = resolve_type(); - if ( data_->bases.contains(base_type) ) { + + if ( auto&& [_, success] = data_->bases.emplace(base_type); !success ) { return *this; } - data_->bases.emplace(base_type); - data_->bases_info.emplace(base_type, detail::class_type_data::base_info{ - .upcast = +[](void* derived) -> void* { - return static_cast(static_cast(derived)); - } - }); + META_HPP_TRY { + data_->bases_info.emplace(base_type, detail::class_type_data::base_info{ + .upcast = +[](void* derived) -> void* { + return static_cast(static_cast(derived)); + } + }); + } META_HPP_CATCH(...) { + data_->bases.erase(base_type); + META_HPP_RETHROW(); + } return *this; } diff --git a/headers/meta.hpp/meta_detail/type_registry.hpp b/headers/meta.hpp/meta_detail/type_registry.hpp index 9762098..0f2a1fc 100644 --- a/headers/meta.hpp/meta_detail/type_registry.hpp +++ b/headers/meta.hpp/meta_detail/type_registry.hpp @@ -221,8 +221,13 @@ namespace meta_hpp::detail std::call_once(init_flag, [this, &type_data](){ const locker lock; type_by_id_.emplace(type_data.id, any_type{&type_data}); - #ifndef META_HPP_NO_RTTI - type_by_rtti_.emplace(typeid(Type), any_type{&type_data}); + #if !defined(META_HPP_NO_RTTI) + META_HPP_TRY { + type_by_rtti_.emplace(typeid(Type), any_type{&type_data}); + } META_HPP_CATCH(...) { + type_by_id_.erase(type_data.id); + META_HPP_RETHROW(); + } #endif }); } diff --git a/headers/meta.hpp/meta_registry.hpp b/headers/meta.hpp/meta_registry.hpp index b3606d0..48379e6 100644 --- a/headers/meta.hpp/meta_registry.hpp +++ b/headers/meta.hpp/meta_registry.hpp @@ -62,7 +62,7 @@ namespace meta_hpp { template < typename T > [[nodiscard]] any_type resolve_polymorphic_type(T&& v) noexcept { - #ifndef META_HPP_NO_RTTI + #if !defined(META_HPP_NO_RTTI) using namespace detail; type_registry& registry = type_registry::instance(); return registry.get_type_by_rtti(typeid(v)); diff --git a/headers/meta.hpp/meta_states/constructor.hpp b/headers/meta.hpp/meta_states/constructor.hpp index 738bb70..43efa53 100644 --- a/headers/meta.hpp/meta_states/constructor.hpp +++ b/headers/meta.hpp/meta_states/constructor.hpp @@ -115,18 +115,13 @@ namespace meta_hpp::detail using ct = constructor_traits; using ct_argument_types = typename ct::argument_types; - argument_list arguments; - arguments.reserve(ct::arity); - - [&arguments](std::index_sequence) mutable { + return [](std::index_sequence){ [[maybe_unused]] const auto make_argument = [](std::index_sequence){ using P = type_list_at_t; return argument{argument_state::make

(I, metadata_map{})}; }; - (arguments.push_back(make_argument(std::index_sequence{})), ...); + return argument_list{make_argument(std::index_sequence{})...}; }(std::make_index_sequence()); - - return arguments; } } diff --git a/headers/meta.hpp/meta_states/function.hpp b/headers/meta.hpp/meta_states/function.hpp index dbd0014..226ff8a 100644 --- a/headers/meta.hpp/meta_states/function.hpp +++ b/headers/meta.hpp/meta_states/function.hpp @@ -98,18 +98,13 @@ namespace meta_hpp::detail using ft = function_traits; using ft_argument_types = typename ft::argument_types; - argument_list arguments; - arguments.reserve(ft::arity); - - [&arguments](std::index_sequence) mutable { + return [](std::index_sequence){ [[maybe_unused]] const auto make_argument = [](std::index_sequence){ using P = type_list_at_t; return argument{argument_state::make

(I, metadata_map{})}; }; - (arguments.push_back(make_argument(std::index_sequence{})), ...); + return argument_list{make_argument(std::index_sequence{})...}; }(std::make_index_sequence()); - - return arguments; } } diff --git a/headers/meta.hpp/meta_states/method.hpp b/headers/meta.hpp/meta_states/method.hpp index cea6362..6ed8f8d 100644 --- a/headers/meta.hpp/meta_states/method.hpp +++ b/headers/meta.hpp/meta_states/method.hpp @@ -109,18 +109,13 @@ namespace meta_hpp::detail using mt = method_traits; using mt_argument_types = typename mt::argument_types; - argument_list arguments; - arguments.reserve(mt::arity); - - [&arguments](std::index_sequence) mutable { + return [](std::index_sequence){ [[maybe_unused]] const auto make_argument = [](std::index_sequence){ using P = type_list_at_t; return argument{argument_state::make

(I, metadata_map{})}; }; - (arguments.push_back(make_argument(std::index_sequence{})), ...); + return argument_list{make_argument(std::index_sequence{})...}; }(std::make_index_sequence()); - - return arguments; } }