From 6a8aa134445d235f935bc0cf6cd9b0a543c6bf82 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Tue, 31 Jan 2023 06:37:54 +0700 Subject: [PATCH] replace all shared to intrusive ptrs --- develop/singles/headers/meta.hpp/meta_all.hpp | 400 +++++++++++++----- .../untests/meta_base/intrusive_ptr_tests.cpp | 215 ++++++++++ headers/meta.hpp/meta_base.hpp | 19 +- headers/meta.hpp/meta_base/intrusive_ptr.hpp | 176 ++++++++ headers/meta.hpp/meta_states.hpp | 73 ++-- headers/meta.hpp/meta_states/argument.hpp | 10 +- headers/meta.hpp/meta_states/constructor.hpp | 18 +- headers/meta.hpp/meta_states/destructor.hpp | 14 +- headers/meta.hpp/meta_states/evalue.hpp | 14 +- headers/meta.hpp/meta_states/function.hpp | 16 +- headers/meta.hpp/meta_states/member.hpp | 18 +- headers/meta.hpp/meta_states/method.hpp | 16 +- headers/meta.hpp/meta_states/scope.hpp | 10 +- headers/meta.hpp/meta_states/variable.hpp | 16 +- headers/meta.hpp/meta_types.hpp | 10 +- 15 files changed, 823 insertions(+), 202 deletions(-) create mode 100644 develop/untests/meta_base/intrusive_ptr_tests.cpp create mode 100644 headers/meta.hpp/meta_base/intrusive_ptr.hpp diff --git a/develop/singles/headers/meta.hpp/meta_all.hpp b/develop/singles/headers/meta.hpp/meta_all.hpp index 44a1d91..720734e 100644 --- a/develop/singles/headers/meta.hpp/meta_all.hpp +++ b/develop/singles/headers/meta.hpp/meta_all.hpp @@ -665,6 +665,173 @@ namespace meta_hpp::detail } } +namespace meta_hpp::detail +{ + template < typename Derived > + class intrusive_ref_counter; + + template < typename Derived > + void intrusive_ptr_add_ref(const intrusive_ref_counter* ptr); + + template < typename Derived > + void intrusive_ptr_release(const intrusive_ref_counter* ptr); + + template < typename Derived > + class intrusive_ref_counter { + public: + intrusive_ref_counter() = default; + + intrusive_ref_counter(intrusive_ref_counter&&) noexcept {} + intrusive_ref_counter(const intrusive_ref_counter&) noexcept {} + + intrusive_ref_counter& operator=(intrusive_ref_counter&&) noexcept { return *this; } + intrusive_ref_counter& operator=(const intrusive_ref_counter&) noexcept { return *this; } + + [[nodiscard]] std::size_t get_use_count() const noexcept { + return counter_.load(std::memory_order_acquire); + } + protected: + ~intrusive_ref_counter() = default; + private: + mutable std::atomic_size_t counter_{}; + + friend void intrusive_ptr_add_ref(const intrusive_ref_counter* ptr) { + ptr->counter_.fetch_add(1, std::memory_order_acq_rel); + } + + friend void intrusive_ptr_release(const intrusive_ref_counter* ptr) { + if ( ptr->counter_.fetch_sub(1, std::memory_order_acq_rel) == 1 ) { + std::unique_ptr(static_cast(ptr)).reset(); + } + } + }; +} + +namespace meta_hpp::detail +{ + template < typename T > + class intrusive_ptr final { + public: + intrusive_ptr() = default; + + ~intrusive_ptr() { + if ( ptr_ != nullptr ) { + intrusive_ptr_release(ptr_); + } + } + + intrusive_ptr(T* ptr, bool add_ref = true) + : ptr_{ptr} { + if ( ptr_ != nullptr && add_ref ) { + intrusive_ptr_add_ref(ptr_); + } + } + + intrusive_ptr(intrusive_ptr&& other) noexcept + : ptr_{other.ptr_} { + other.ptr_ = nullptr; + } + + intrusive_ptr(const intrusive_ptr& other) + : ptr_{other.ptr_} { + if ( ptr_ != nullptr ) { + intrusive_ptr_add_ref(ptr_); + } + } + + intrusive_ptr& operator=(T* ptr) noexcept { + intrusive_ptr{ptr}.swap(*this); + return *this; + } + + intrusive_ptr& operator=(intrusive_ptr&& other) noexcept { + intrusive_ptr{std::move(other)}.swap(*this); + return *this; + } + + intrusive_ptr& operator=(const intrusive_ptr& other) { + intrusive_ptr{other}.swap(*this); + return *this; + } + + void reset() { + intrusive_ptr{}.swap(*this); + } + + void reset(T* ptr) { + intrusive_ptr{ptr}.swap(*this); + } + + void reset(T* ptr, bool add_ref) { + intrusive_ptr{ptr, add_ref}.swap(*this); + } + + T* release() noexcept { + return std::exchange(ptr_, nullptr); + } + + [[nodiscard]] T* get() const noexcept { + return ptr_; + } + + [[nodiscard]] T& operator*() const noexcept { + return *ptr_; + } + + [[nodiscard]] T* operator->() const noexcept { + return ptr_; + } + + [[nodiscard]] explicit operator bool() const noexcept { + return ptr_ != nullptr; + } + + void swap(intrusive_ptr& other) noexcept { + ptr_ = std::exchange(other.ptr_, ptr_); + } + private: + T* ptr_{}; + }; + + template < typename T, typename... Args > + intrusive_ptr make_intrusive(Args&&... args) { + return std::make_unique(std::forward(args)...).release(); + } + + template < typename T > + void swap(intrusive_ptr& l, intrusive_ptr& r) noexcept { return l.swap(r); } + + template < typename T > + bool operator==(const intrusive_ptr& l, const intrusive_ptr& r) noexcept { return l.get() == r.get(); } + + template < typename T > + bool operator!=(const intrusive_ptr& l, const intrusive_ptr& r) noexcept { return l.get() != r.get(); } + + template < typename T > + bool operator==(const intrusive_ptr& l, const T* r) noexcept { return l.get() == r; } + + template < typename T > + bool operator==(const T* l, const intrusive_ptr& r) noexcept { return l == r.get(); } + + template < typename T > + bool operator!=(const intrusive_ptr& l, const T* r) noexcept { return l.get() != r; } + + template < typename T > + bool operator!=(const T* l, const intrusive_ptr& r) noexcept { return l != r.get(); } + + template < typename T > + bool operator==(const intrusive_ptr& l, std::nullptr_t) noexcept { return !l; } + + template < typename T > + bool operator==(std::nullptr_t, const intrusive_ptr& r) noexcept { return !r; } + + template < typename T > + bool operator!=(const intrusive_ptr& l, std::nullptr_t) noexcept { return !!l; } + + template < typename T > + bool operator!=(std::nullptr_t, const intrusive_ptr& r) noexcept { return !!r; } +} + namespace meta_hpp::detail { template < typename T > @@ -1027,15 +1194,15 @@ namespace meta_hpp struct scope_state; struct variable_state; - using argument_state_ptr = std::shared_ptr; - using constructor_state_ptr = std::shared_ptr; - using destructor_state_ptr = std::shared_ptr; - using evalue_state_ptr = std::shared_ptr; - using function_state_ptr = std::shared_ptr; - using member_state_ptr = std::shared_ptr; - using method_state_ptr = std::shared_ptr; - using scope_state_ptr = std::shared_ptr; - using variable_state_ptr = std::shared_ptr; + using argument_state_ptr = intrusive_ptr; + using constructor_state_ptr = intrusive_ptr; + using destructor_state_ptr = intrusive_ptr; + using evalue_state_ptr = intrusive_ptr; + using function_state_ptr = intrusive_ptr; + using member_state_ptr = intrusive_ptr; + using method_state_ptr = intrusive_ptr; + using scope_state_ptr = intrusive_ptr; + using variable_state_ptr = intrusive_ptr; } } @@ -2160,11 +2327,19 @@ namespace meta_hpp::detail const type_id id; const type_kind kind; - metadata_map metadata; + metadata_map metadata{}; explicit type_data_base(type_id nid, type_kind nkind) : id{nid} , kind{nkind} {} + + type_data_base(type_data_base&&) = delete; + type_data_base(const type_data_base&) = delete; + type_data_base& operator=(type_data_base&&) = delete; + type_data_base& operator=(const type_data_base&) = delete; + + protected: + ~type_data_base() = default; }; struct array_type_data final : type_data_base { @@ -3138,7 +3313,7 @@ namespace meta_hpp namespace meta_hpp::detail { - struct argument_state final { + struct argument_state final : intrusive_ref_counter { argument_index index; metadata_map metadata; @@ -3146,9 +3321,10 @@ namespace meta_hpp::detail template < typename Argument > [[nodiscard]] static argument_state_ptr make(std::size_t position, metadata_map metadata); + explicit argument_state(argument_index index, metadata_map metadata); }; - struct constructor_state final { + struct constructor_state final : intrusive_ref_counter { using create_impl = fixed_function)>; using create_at_impl = fixed_function)>; using is_invocable_with_impl = fixed_function)>; @@ -3156,58 +3332,60 @@ namespace meta_hpp::detail constructor_index index; metadata_map metadata; - create_impl create; - create_at_impl create_at; - is_invocable_with_impl is_invocable_with; - - argument_list arguments; + create_impl create{}; + create_at_impl create_at{}; + is_invocable_with_impl is_invocable_with{}; + argument_list arguments{}; template < constructor_policy_kind Policy, class_kind Class, typename... Args > [[nodiscard]] static constructor_state_ptr make(metadata_map metadata); + explicit constructor_state(constructor_index index, metadata_map metadata); }; - struct destructor_state final { + struct destructor_state final : intrusive_ref_counter { using destroy_impl = fixed_function; using destroy_at_impl = fixed_function; destructor_index index; metadata_map metadata; - destroy_impl destroy; - destroy_at_impl destroy_at; + destroy_impl destroy{}; + destroy_at_impl destroy_at{}; template < class_kind Class > [[nodiscard]] static destructor_state_ptr make(metadata_map metadata); + explicit destructor_state(destructor_index index, metadata_map metadata); }; - struct evalue_state final { + struct evalue_state final : intrusive_ref_counter { evalue_index index; metadata_map metadata; - uvalue enum_value; - uvalue underlying_value; + uvalue enum_value{}; + uvalue underlying_value{}; template < enum_kind Enum > [[nodiscard]] static evalue_state_ptr make(std::string name, Enum evalue, metadata_map metadata); + explicit evalue_state(evalue_index index, metadata_map metadata); }; - struct function_state final { + struct function_state final : intrusive_ref_counter { using invoke_impl = fixed_function)>; using is_invocable_with_impl = fixed_function)>; function_index index; metadata_map metadata; - invoke_impl invoke; - is_invocable_with_impl is_invocable_with; - - argument_list arguments; + invoke_impl invoke{}; + is_invocable_with_impl is_invocable_with{}; + argument_list arguments{}; template < function_policy_kind Policy, function_kind Function > [[nodiscard]] static function_state_ptr make(std::string name, Function function, metadata_map metadata); + explicit function_state(function_index index, metadata_map metadata); }; - struct member_state final { + struct member_state final : intrusive_ref_counter { using getter_impl = fixed_function; using setter_impl = fixed_function; @@ -3217,33 +3395,33 @@ namespace meta_hpp::detail member_index index; metadata_map metadata; - getter_impl getter; - setter_impl setter; - is_gettable_with_impl is_gettable_with; - is_settable_with_impl is_settable_with; - + getter_impl getter{}; + setter_impl setter{}; + is_gettable_with_impl is_gettable_with{}; + is_settable_with_impl is_settable_with{}; template < member_policy_kind Policy, member_kind Member > [[nodiscard]] static member_state_ptr make(std::string name, Member member, metadata_map metadata); + explicit member_state(member_index index, metadata_map metadata); }; - struct method_state final { + struct method_state final : intrusive_ref_counter { using invoke_impl = fixed_function)>; using is_invocable_with_impl = fixed_function)>; method_index index; metadata_map metadata; - invoke_impl invoke; - is_invocable_with_impl is_invocable_with; - - argument_list arguments; + invoke_impl invoke{}; + is_invocable_with_impl is_invocable_with{}; + argument_list arguments{}; template < method_policy_kind Policy, method_kind Method > [[nodiscard]] static method_state_ptr make(std::string name, Method method, metadata_map metadata); + explicit method_state(method_index index, metadata_map metadata); }; - struct scope_state final { + struct scope_state final : intrusive_ref_counter { scope_index index; metadata_map metadata; @@ -3252,9 +3430,10 @@ namespace meta_hpp::detail variable_set variables{}; [[nodiscard]] static scope_state_ptr make(std::string name, metadata_map metadata); + explicit scope_state(scope_index index, metadata_map metadata); }; - struct variable_state final { + struct variable_state final : intrusive_ref_counter { using getter_impl = fixed_function; using setter_impl = fixed_function; using is_settable_with_impl = fixed_function; @@ -3262,12 +3441,13 @@ namespace meta_hpp::detail variable_index index; metadata_map metadata; - getter_impl getter; - setter_impl setter; - is_settable_with_impl is_settable_with; + getter_impl getter{}; + setter_impl setter{}; + is_settable_with_impl is_settable_with{}; template < variable_policy_kind Policy, pointer_kind Pointer > [[nodiscard]] static variable_state_ptr make(std::string name, Pointer pointer, metadata_map metadata); + explicit variable_state(variable_index index, metadata_map metadata); }; } @@ -4943,12 +5123,14 @@ namespace meta_hpp namespace meta_hpp::detail { + inline argument_state::argument_state(argument_index nindex, metadata_map nmetadata) + : index{nindex} + , metadata{std::move(nmetadata)} {} + template < typename Argument > inline argument_state_ptr argument_state::make(std::size_t position, metadata_map metadata) { - return std::make_shared(argument_state{ - .index{argument_index::make(position)}, - .metadata{std::move(metadata)}, - }); + argument_state state{argument_index::make(position), std::move(metadata)}; + return make_intrusive(std::move(state)); } } @@ -5620,16 +5802,18 @@ namespace meta_hpp::detail namespace meta_hpp::detail { + inline constructor_state::constructor_state(constructor_index nindex, metadata_map nmetadata) + : index{nindex} + , metadata{std::move(nmetadata)} {} + template < constructor_policy_kind Policy, class_kind Class, typename... Args > constructor_state_ptr constructor_state::make(metadata_map metadata) { - return std::make_shared(constructor_state{ - .index{constructor_index::make()}, - .metadata{std::move(metadata)}, - .create{make_constructor_create()}, - .create_at{make_constructor_create_at()}, - .is_invocable_with{make_constructor_is_invocable_with()}, - .arguments{make_constructor_arguments()}, - }); + constructor_state state{constructor_index::make(), std::move(metadata)}; + state.create = make_constructor_create(); + state.create_at = make_constructor_create_at(); + state.is_invocable_with = make_constructor_is_invocable_with(); + state.arguments = make_constructor_arguments(); + return make_intrusive(std::move(state)); } } @@ -5792,14 +5976,16 @@ namespace meta_hpp::detail namespace meta_hpp::detail { + inline destructor_state::destructor_state(destructor_index nindex, metadata_map nmetadata) + : index{nindex} + , metadata{std::move(nmetadata)} {} + template < class_kind Class > destructor_state_ptr destructor_state::make(metadata_map metadata) { - return std::make_shared(destructor_state{ - .index{destructor_index::make()}, - .metadata{std::move(metadata)}, - .destroy{make_destructor_destroy()}, - .destroy_at{make_destructor_destroy_at()}, - }); + destructor_state state{destructor_index::make(), std::move(metadata)}; + state.destroy = make_destructor_destroy(); + state.destroy_at = make_destructor_destroy_at(); + return make_intrusive(std::move(state)); } } @@ -5925,14 +6111,16 @@ namespace meta_hpp namespace meta_hpp::detail { + inline evalue_state::evalue_state(evalue_index nindex, metadata_map nmetadata) + : index{std::move(nindex)} + , metadata{std::move(nmetadata)} {} + template < enum_kind Enum > evalue_state_ptr evalue_state::make(std::string name, Enum evalue, metadata_map metadata) { - return std::make_shared(evalue_state{ - .index{evalue_index::make(std::move(name))}, - .metadata{std::move(metadata)}, - .enum_value{uvalue{evalue}}, - .underlying_value{uvalue{to_underlying(evalue)}}, - }); + evalue_state state{evalue_index::make(std::move(name)), std::move(metadata)}; + state.enum_value = uvalue{evalue}; + state.underlying_value = uvalue{to_underlying(evalue)}; + return make_intrusive(std::move(state)); } } @@ -6137,15 +6325,17 @@ namespace meta_hpp::detail namespace meta_hpp::detail { + inline function_state::function_state(function_index nindex, metadata_map nmetadata) + : index{std::move(nindex)} + , metadata{std::move(nmetadata)} {} + template < function_policy_kind Policy, function_kind Function > function_state_ptr function_state::make(std::string name, Function function, metadata_map metadata) { - return std::make_shared(function_state{ - .index{function_index::make(std::move(name))}, - .metadata{std::move(metadata)}, - .invoke{make_function_invoke(std::move(function))}, - .is_invocable_with{make_function_is_invocable_with()}, - .arguments{make_function_arguments()}, - }); + function_state state{function_index::make(std::move(name)), std::move(metadata)}; + state.invoke = make_function_invoke(std::move(function)); + state.is_invocable_with = make_function_is_invocable_with(); + state.arguments = make_function_arguments(); + return make_intrusive(std::move(state)); } } @@ -6634,16 +6824,18 @@ namespace meta_hpp::detail namespace meta_hpp::detail { + inline member_state::member_state(member_index nindex, metadata_map nmetadata) + : index{std::move(nindex)} + , metadata{std::move(nmetadata)} {} + template < member_policy_kind Policy, member_kind Member > member_state_ptr member_state::make(std::string name, Member member, metadata_map metadata) { - return std::make_shared(member_state{ - .index{member_index::make(std::move(name))}, - .metadata{std::move(metadata)}, - .getter{make_member_getter(member)}, - .setter{make_member_setter(member)}, - .is_gettable_with{make_member_is_gettable_with()}, - .is_settable_with{make_member_is_settable_with()}, - }); + member_state state{member_index::make(std::move(name)), std::move(metadata)}; + state.getter = make_member_getter(member); + state.setter = make_member_setter(member); + state.is_gettable_with = make_member_is_gettable_with(); + state.is_settable_with = make_member_is_settable_with(); + return make_intrusive(std::move(state)); } } @@ -6905,15 +7097,17 @@ namespace meta_hpp::detail namespace meta_hpp::detail { + inline method_state::method_state(method_index nindex, metadata_map nmetadata) + : index{std::move(nindex)} + , metadata{std::move(nmetadata)} {} + template < method_policy_kind Policy, method_kind Method > method_state_ptr method_state::make(std::string name, Method method, metadata_map metadata) { - return std::make_shared(method_state{ - .index{method_index::make(std::move(name))}, - .metadata{std::move(metadata)}, - .invoke{make_method_invoke(std::move(method))}, - .is_invocable_with{make_method_is_invocable_with()}, - .arguments{make_method_arguments()}, - }); + method_state state{method_index::make(std::move(name)), std::move(metadata)}; + state.invoke = make_method_invoke(std::move(method)); + state.is_invocable_with = make_method_is_invocable_with(); + state.arguments = make_method_arguments(); + return make_intrusive(std::move(state)); } } @@ -7121,15 +7315,17 @@ namespace meta_hpp::detail namespace meta_hpp::detail { + inline variable_state::variable_state(variable_index nindex, metadata_map nmetadata) + : index{std::move(nindex)} + , metadata{std::move(nmetadata)} {} + template < variable_policy_kind Policy, pointer_kind Pointer > variable_state_ptr variable_state::make(std::string name, Pointer pointer, metadata_map metadata) { - return std::make_shared(variable_state{ - .index{variable_index::make(std::move(name))}, - .metadata{std::move(metadata)}, - .getter{make_variable_getter(pointer)}, - .setter{make_variable_setter(pointer)}, - .is_settable_with{make_variable_is_settable_with()}, - }); + variable_state state{variable_index::make(std::move(name)), std::move(metadata)}; + state.getter = make_variable_getter(pointer); + state.setter = make_variable_setter(pointer); + state.is_settable_with = make_variable_is_settable_with(); + return make_intrusive(std::move(state)); } } @@ -7575,11 +7771,13 @@ namespace meta_hpp namespace meta_hpp::detail { + inline scope_state::scope_state(scope_index nindex, metadata_map nmetadata) + : index{std::move(nindex)} + , metadata{std::move(nmetadata)} {} + inline scope_state_ptr scope_state::make(std::string name, metadata_map metadata) { - return std::make_shared(scope_state{ - .index{scope_index::make(std::move(name))}, - .metadata{std::move(metadata)}, - }); + scope_state state{scope_index::make(std::move(name)), std::move(metadata)}; + return make_intrusive(std::move(state)); } } diff --git a/develop/untests/meta_base/intrusive_ptr_tests.cpp b/develop/untests/meta_base/intrusive_ptr_tests.cpp new file mode 100644 index 0000000..2418f72 --- /dev/null +++ b/develop/untests/meta_base/intrusive_ptr_tests.cpp @@ -0,0 +1,215 @@ +/******************************************************************************* + * This file is part of the "https://github.com/blackmatov/meta.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2021-2023, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#include +#include + +namespace +{ + namespace meta = meta_hpp; + using meta::detail::intrusive_ptr; + using meta::detail::intrusive_ref_counter; + + struct obj_t final : intrusive_ref_counter { + int v{42}; + + obj_t() { ++ctor_counter; } + obj_t(int nv) : v{nv} { ++ctor_counter; } + ~obj_t() { ++dtor_counter; } + + inline static std::size_t ctor_counter{}; + inline static std::size_t dtor_counter{}; + }; +} + +TEST_CASE("meta/meta_base/intrusive_ptr") { + obj_t::ctor_counter = 0; + obj_t::dtor_counter = 0; + + SUBCASE("ctor/0") { + intrusive_ptr ptr; + CHECK_FALSE(ptr); + } + + SUBCASE("copy_ctor/0") { + intrusive_ptr ptr; + intrusive_ptr ptr2{ptr}; + CHECK_FALSE(ptr2); + } + + SUBCASE("move_ctor/0") { + intrusive_ptr ptr; + intrusive_ptr ptr2{std::move(ptr)}; + CHECK_FALSE(ptr2); + } + + SUBCASE("ctor/1") { + { + intrusive_ptr ptr{std::make_unique().release()}; + CHECK(ptr); + CHECK(ptr->get_use_count() == 1); + CHECK(ptr->v == 42); + CHECK(obj_t::ctor_counter == 1); + CHECK(obj_t::dtor_counter == 0); + } + CHECK(obj_t::ctor_counter == 1); + CHECK(obj_t::dtor_counter == 1); + } + + SUBCASE("copy_ctor/1") { + { + intrusive_ptr ptr{std::make_unique().release()}; + { + intrusive_ptr ptr2{ptr}; + CHECK(ptr); + CHECK(ptr2); + CHECK(ptr2->get_use_count() == 2); + CHECK(ptr2->v == 42); + } + CHECK(obj_t::ctor_counter == 1); + CHECK(obj_t::dtor_counter == 0); + } + CHECK(obj_t::ctor_counter == 1); + CHECK(obj_t::dtor_counter == 1); + } + + SUBCASE("move_ctor/1") { + { + intrusive_ptr ptr{std::make_unique().release()}; + { + intrusive_ptr ptr2{std::move(ptr)}; + CHECK_FALSE(ptr); + CHECK(ptr2); + CHECK(ptr2->get_use_count() == 1); + CHECK(ptr2->v == 42); + } + CHECK(obj_t::ctor_counter == 1); + CHECK(obj_t::dtor_counter == 1); + } + CHECK(obj_t::ctor_counter == 1); + CHECK(obj_t::dtor_counter == 1); + } + + SUBCASE("operator=/ptr") { + { + intrusive_ptr ptr1{std::make_unique().release()}; + ptr1 = std::make_unique().release(); + CHECK(obj_t::ctor_counter == 2); + CHECK(obj_t::dtor_counter == 1); + } + CHECK(obj_t::ctor_counter == 2); + CHECK(obj_t::dtor_counter == 2); + } + + SUBCASE("operator=/copy") { + { + intrusive_ptr ptr1{std::make_unique().release()}; + intrusive_ptr ptr2{std::make_unique().release()}; + ptr1 = ptr2; + CHECK(ptr1); + CHECK(ptr2); + CHECK(obj_t::ctor_counter == 2); + CHECK(obj_t::dtor_counter == 1); + } + CHECK(obj_t::ctor_counter == 2); + CHECK(obj_t::dtor_counter == 2); + } + + SUBCASE("operator=/move") { + { + intrusive_ptr ptr1{std::make_unique().release()}; + intrusive_ptr ptr2{std::make_unique().release()}; + ptr1 = std::move(ptr2); + CHECK(ptr1); + CHECK_FALSE(ptr2); + CHECK(obj_t::ctor_counter == 2); + CHECK(obj_t::dtor_counter == 1); + } + CHECK(obj_t::ctor_counter == 2); + CHECK(obj_t::dtor_counter == 2); + } + + SUBCASE("reset/0") { + intrusive_ptr ptr{std::make_unique().release()}; + ptr.reset(); + CHECK(obj_t::ctor_counter == 1); + CHECK(obj_t::dtor_counter == 1); + } + + SUBCASE("reset/1") { + { + intrusive_ptr ptr{std::make_unique().release()}; + ptr.reset(std::make_unique().release()); + CHECK(obj_t::ctor_counter == 2); + CHECK(obj_t::dtor_counter == 1); + } + CHECK(obj_t::ctor_counter == 2); + CHECK(obj_t::dtor_counter == 2); + } + + SUBCASE("get") { + intrusive_ptr ptr{std::make_unique().release()}; + CHECK(ptr.get()->v == 42); + CHECK(ptr->v == 42); + CHECK((*ptr).v == 42); + ptr.reset(); + CHECK_FALSE(ptr.get()); + } + + SUBCASE("release") { + obj_t* obj{}; + { + intrusive_ptr ptr{std::make_unique().release()}; + obj = ptr.release(); + CHECK_FALSE(ptr); + } + CHECK(obj_t::ctor_counter == 1); + CHECK(obj_t::dtor_counter == 0); + { + intrusive_ptr ptr2{obj, false}; + CHECK(ptr2->get_use_count() == 1); + } + CHECK(obj_t::ctor_counter == 1); + CHECK(obj_t::dtor_counter == 1); + } + + SUBCASE("swap") { + intrusive_ptr ptr1{std::make_unique(42).release()}; + intrusive_ptr ptr2{std::make_unique(21).release()}; + swap(ptr1, ptr2); + CHECK(ptr1->v == 21); + CHECK(ptr2->v == 42); + } + + SUBCASE("operator==/!=") { + intrusive_ptr ptr1{std::make_unique(42).release()}; + intrusive_ptr ptr1_copy{ptr1}; + intrusive_ptr ptr2{std::make_unique(42).release()}; + intrusive_ptr ptr3; + + CHECK(ptr1 == ptr1_copy); + CHECK(ptr1 == ptr1_copy.get()); + CHECK(ptr1_copy.get() == ptr1); + CHECK_FALSE(ptr1 == ptr2); + CHECK_FALSE(ptr1 == ptr3); + + CHECK_FALSE(ptr1 != ptr1_copy); + CHECK_FALSE(ptr1 != ptr1_copy.get()); + CHECK_FALSE(ptr1_copy.get() != ptr1); + CHECK(ptr1 != ptr2); + CHECK(ptr1 != ptr3); + + CHECK_FALSE(ptr1 == nullptr); + CHECK_FALSE(nullptr == ptr1); + CHECK(ptr1 != nullptr); + CHECK(nullptr != ptr1); + + CHECK(ptr3 == nullptr); + CHECK(nullptr == ptr3); + CHECK_FALSE(ptr3 != nullptr); + CHECK_FALSE(nullptr != ptr3); + } +} diff --git a/headers/meta.hpp/meta_base.hpp b/headers/meta.hpp/meta_base.hpp index 4fa0f1d..bc3d51d 100644 --- a/headers/meta.hpp/meta_base.hpp +++ b/headers/meta.hpp/meta_base.hpp @@ -15,6 +15,7 @@ #include "meta_base/hash_combiner.hpp" #include "meta_base/hashed_string.hpp" #include "meta_base/insert_or_assign.hpp" +#include "meta_base/intrusive_ptr.hpp" #include "meta_base/is_in_place_type.hpp" #include "meta_base/memory_buffer.hpp" #include "meta_base/noncopyable.hpp" @@ -81,15 +82,15 @@ namespace meta_hpp struct scope_state; struct variable_state; - using argument_state_ptr = std::shared_ptr; - using constructor_state_ptr = std::shared_ptr; - using destructor_state_ptr = std::shared_ptr; - using evalue_state_ptr = std::shared_ptr; - using function_state_ptr = std::shared_ptr; - using member_state_ptr = std::shared_ptr; - using method_state_ptr = std::shared_ptr; - using scope_state_ptr = std::shared_ptr; - using variable_state_ptr = std::shared_ptr; + using argument_state_ptr = intrusive_ptr; + using constructor_state_ptr = intrusive_ptr; + using destructor_state_ptr = intrusive_ptr; + using evalue_state_ptr = intrusive_ptr; + using function_state_ptr = intrusive_ptr; + using member_state_ptr = intrusive_ptr; + using method_state_ptr = intrusive_ptr; + using scope_state_ptr = intrusive_ptr; + using variable_state_ptr = intrusive_ptr; } } diff --git a/headers/meta.hpp/meta_base/intrusive_ptr.hpp b/headers/meta.hpp/meta_base/intrusive_ptr.hpp new file mode 100644 index 0000000..7f8459d --- /dev/null +++ b/headers/meta.hpp/meta_base/intrusive_ptr.hpp @@ -0,0 +1,176 @@ +/******************************************************************************* + * This file is part of the "https://github.com/blackmatov/meta.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2021-2023, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +#include "base.hpp" + +namespace meta_hpp::detail +{ + template < typename Derived > + class intrusive_ref_counter; + + template < typename Derived > + void intrusive_ptr_add_ref(const intrusive_ref_counter* ptr); + + template < typename Derived > + void intrusive_ptr_release(const intrusive_ref_counter* ptr); + + template < typename Derived > + class intrusive_ref_counter { + public: + intrusive_ref_counter() = default; + + intrusive_ref_counter(intrusive_ref_counter&&) noexcept {} + intrusive_ref_counter(const intrusive_ref_counter&) noexcept {} + + intrusive_ref_counter& operator=(intrusive_ref_counter&&) noexcept { return *this; } + intrusive_ref_counter& operator=(const intrusive_ref_counter&) noexcept { return *this; } + + [[nodiscard]] std::size_t get_use_count() const noexcept { + return counter_.load(std::memory_order_acquire); + } + protected: + ~intrusive_ref_counter() = default; + private: + mutable std::atomic_size_t counter_{}; + + friend void intrusive_ptr_add_ref(const intrusive_ref_counter* ptr) { + ptr->counter_.fetch_add(1, std::memory_order_acq_rel); + } + + friend void intrusive_ptr_release(const intrusive_ref_counter* ptr) { + if ( ptr->counter_.fetch_sub(1, std::memory_order_acq_rel) == 1 ) { + std::unique_ptr(static_cast(ptr)).reset(); + } + } + }; +} + +namespace meta_hpp::detail +{ + template < typename T > + class intrusive_ptr final { + public: + intrusive_ptr() = default; + + ~intrusive_ptr() { + if ( ptr_ != nullptr ) { + intrusive_ptr_release(ptr_); + } + } + + intrusive_ptr(T* ptr, bool add_ref = true) + : ptr_{ptr} { + if ( ptr_ != nullptr && add_ref ) { + intrusive_ptr_add_ref(ptr_); + } + } + + intrusive_ptr(intrusive_ptr&& other) noexcept + : ptr_{other.ptr_} { + other.ptr_ = nullptr; + } + + intrusive_ptr(const intrusive_ptr& other) + : ptr_{other.ptr_} { + if ( ptr_ != nullptr ) { + intrusive_ptr_add_ref(ptr_); + } + } + + intrusive_ptr& operator=(T* ptr) noexcept { + intrusive_ptr{ptr}.swap(*this); + return *this; + } + + intrusive_ptr& operator=(intrusive_ptr&& other) noexcept { + intrusive_ptr{std::move(other)}.swap(*this); + return *this; + } + + intrusive_ptr& operator=(const intrusive_ptr& other) { + intrusive_ptr{other}.swap(*this); + return *this; + } + + void reset() { + intrusive_ptr{}.swap(*this); + } + + void reset(T* ptr) { + intrusive_ptr{ptr}.swap(*this); + } + + void reset(T* ptr, bool add_ref) { + intrusive_ptr{ptr, add_ref}.swap(*this); + } + + T* release() noexcept { + return std::exchange(ptr_, nullptr); + } + + [[nodiscard]] T* get() const noexcept { + return ptr_; + } + + [[nodiscard]] T& operator*() const noexcept { + return *ptr_; + } + + [[nodiscard]] T* operator->() const noexcept { + return ptr_; + } + + [[nodiscard]] explicit operator bool() const noexcept { + return ptr_ != nullptr; + } + + void swap(intrusive_ptr& other) noexcept { + ptr_ = std::exchange(other.ptr_, ptr_); + } + private: + T* ptr_{}; + }; + + template < typename T, typename... Args > + intrusive_ptr make_intrusive(Args&&... args) { + return std::make_unique(std::forward(args)...).release(); + } + + template < typename T > + void swap(intrusive_ptr& l, intrusive_ptr& r) noexcept { return l.swap(r); } + + template < typename T > + bool operator==(const intrusive_ptr& l, const intrusive_ptr& r) noexcept { return l.get() == r.get(); } + + template < typename T > + bool operator!=(const intrusive_ptr& l, const intrusive_ptr& r) noexcept { return l.get() != r.get(); } + + template < typename T > + bool operator==(const intrusive_ptr& l, const T* r) noexcept { return l.get() == r; } + + template < typename T > + bool operator==(const T* l, const intrusive_ptr& r) noexcept { return l == r.get(); } + + template < typename T > + bool operator!=(const intrusive_ptr& l, const T* r) noexcept { return l.get() != r; } + + template < typename T > + bool operator!=(const T* l, const intrusive_ptr& r) noexcept { return l != r.get(); } + + template < typename T > + bool operator==(const intrusive_ptr& l, std::nullptr_t) noexcept { return !l; } + + template < typename T > + bool operator==(std::nullptr_t, const intrusive_ptr& r) noexcept { return !r; } + + template < typename T > + bool operator!=(const intrusive_ptr& l, std::nullptr_t) noexcept { return !!l; } + + template < typename T > + bool operator!=(std::nullptr_t, const intrusive_ptr& r) noexcept { return !!r; } +} diff --git a/headers/meta.hpp/meta_states.hpp b/headers/meta.hpp/meta_states.hpp index 09871c4..7f7aef5 100644 --- a/headers/meta.hpp/meta_states.hpp +++ b/headers/meta.hpp/meta_states.hpp @@ -487,7 +487,7 @@ namespace meta_hpp namespace meta_hpp::detail { - struct argument_state final { + struct argument_state final : intrusive_ref_counter { argument_index index; metadata_map metadata; @@ -495,9 +495,10 @@ namespace meta_hpp::detail template < typename Argument > [[nodiscard]] static argument_state_ptr make(std::size_t position, metadata_map metadata); + explicit argument_state(argument_index index, metadata_map metadata); }; - struct constructor_state final { + struct constructor_state final : intrusive_ref_counter { using create_impl = fixed_function)>; using create_at_impl = fixed_function)>; using is_invocable_with_impl = fixed_function)>; @@ -505,58 +506,60 @@ namespace meta_hpp::detail constructor_index index; metadata_map metadata; - create_impl create; - create_at_impl create_at; - is_invocable_with_impl is_invocable_with; - - argument_list arguments; + create_impl create{}; + create_at_impl create_at{}; + is_invocable_with_impl is_invocable_with{}; + argument_list arguments{}; template < constructor_policy_kind Policy, class_kind Class, typename... Args > [[nodiscard]] static constructor_state_ptr make(metadata_map metadata); + explicit constructor_state(constructor_index index, metadata_map metadata); }; - struct destructor_state final { + struct destructor_state final : intrusive_ref_counter { using destroy_impl = fixed_function; using destroy_at_impl = fixed_function; destructor_index index; metadata_map metadata; - destroy_impl destroy; - destroy_at_impl destroy_at; + destroy_impl destroy{}; + destroy_at_impl destroy_at{}; template < class_kind Class > [[nodiscard]] static destructor_state_ptr make(metadata_map metadata); + explicit destructor_state(destructor_index index, metadata_map metadata); }; - struct evalue_state final { + struct evalue_state final : intrusive_ref_counter { evalue_index index; metadata_map metadata; - uvalue enum_value; - uvalue underlying_value; + uvalue enum_value{}; + uvalue underlying_value{}; template < enum_kind Enum > [[nodiscard]] static evalue_state_ptr make(std::string name, Enum evalue, metadata_map metadata); + explicit evalue_state(evalue_index index, metadata_map metadata); }; - struct function_state final { + struct function_state final : intrusive_ref_counter { using invoke_impl = fixed_function)>; using is_invocable_with_impl = fixed_function)>; function_index index; metadata_map metadata; - invoke_impl invoke; - is_invocable_with_impl is_invocable_with; - - argument_list arguments; + invoke_impl invoke{}; + is_invocable_with_impl is_invocable_with{}; + argument_list arguments{}; template < function_policy_kind Policy, function_kind Function > [[nodiscard]] static function_state_ptr make(std::string name, Function function, metadata_map metadata); + explicit function_state(function_index index, metadata_map metadata); }; - struct member_state final { + struct member_state final : intrusive_ref_counter { using getter_impl = fixed_function; using setter_impl = fixed_function; @@ -566,33 +569,33 @@ namespace meta_hpp::detail member_index index; metadata_map metadata; - getter_impl getter; - setter_impl setter; - is_gettable_with_impl is_gettable_with; - is_settable_with_impl is_settable_with; - + getter_impl getter{}; + setter_impl setter{}; + is_gettable_with_impl is_gettable_with{}; + is_settable_with_impl is_settable_with{}; template < member_policy_kind Policy, member_kind Member > [[nodiscard]] static member_state_ptr make(std::string name, Member member, metadata_map metadata); + explicit member_state(member_index index, metadata_map metadata); }; - struct method_state final { + struct method_state final : intrusive_ref_counter { using invoke_impl = fixed_function)>; using is_invocable_with_impl = fixed_function)>; method_index index; metadata_map metadata; - invoke_impl invoke; - is_invocable_with_impl is_invocable_with; - - argument_list arguments; + invoke_impl invoke{}; + is_invocable_with_impl is_invocable_with{}; + argument_list arguments{}; template < method_policy_kind Policy, method_kind Method > [[nodiscard]] static method_state_ptr make(std::string name, Method method, metadata_map metadata); + explicit method_state(method_index index, metadata_map metadata); }; - struct scope_state final { + struct scope_state final : intrusive_ref_counter { scope_index index; metadata_map metadata; @@ -601,9 +604,10 @@ namespace meta_hpp::detail variable_set variables{}; [[nodiscard]] static scope_state_ptr make(std::string name, metadata_map metadata); + explicit scope_state(scope_index index, metadata_map metadata); }; - struct variable_state final { + struct variable_state final : intrusive_ref_counter { using getter_impl = fixed_function; using setter_impl = fixed_function; using is_settable_with_impl = fixed_function; @@ -611,11 +615,12 @@ namespace meta_hpp::detail variable_index index; metadata_map metadata; - getter_impl getter; - setter_impl setter; - is_settable_with_impl is_settable_with; + getter_impl getter{}; + setter_impl setter{}; + is_settable_with_impl is_settable_with{}; template < variable_policy_kind Policy, pointer_kind Pointer > [[nodiscard]] static variable_state_ptr make(std::string name, Pointer pointer, metadata_map metadata); + explicit variable_state(variable_index index, metadata_map metadata); }; } diff --git a/headers/meta.hpp/meta_states/argument.hpp b/headers/meta.hpp/meta_states/argument.hpp index eaeab9a..f901ea2 100644 --- a/headers/meta.hpp/meta_states/argument.hpp +++ b/headers/meta.hpp/meta_states/argument.hpp @@ -11,12 +11,14 @@ namespace meta_hpp::detail { + inline argument_state::argument_state(argument_index nindex, metadata_map nmetadata) + : index{nindex} + , metadata{std::move(nmetadata)} {} + template < typename Argument > inline argument_state_ptr argument_state::make(std::size_t position, metadata_map metadata) { - return std::make_shared(argument_state{ - .index{argument_index::make(position)}, - .metadata{std::move(metadata)}, - }); + argument_state state{argument_index::make(position), std::move(metadata)}; + return make_intrusive(std::move(state)); } } diff --git a/headers/meta.hpp/meta_states/constructor.hpp b/headers/meta.hpp/meta_states/constructor.hpp index eae2936..70138c1 100644 --- a/headers/meta.hpp/meta_states/constructor.hpp +++ b/headers/meta.hpp/meta_states/constructor.hpp @@ -127,16 +127,18 @@ namespace meta_hpp::detail namespace meta_hpp::detail { + inline constructor_state::constructor_state(constructor_index nindex, metadata_map nmetadata) + : index{nindex} + , metadata{std::move(nmetadata)} {} + template < constructor_policy_kind Policy, class_kind Class, typename... Args > constructor_state_ptr constructor_state::make(metadata_map metadata) { - return std::make_shared(constructor_state{ - .index{constructor_index::make()}, - .metadata{std::move(metadata)}, - .create{make_constructor_create()}, - .create_at{make_constructor_create_at()}, - .is_invocable_with{make_constructor_is_invocable_with()}, - .arguments{make_constructor_arguments()}, - }); + constructor_state state{constructor_index::make(), std::move(metadata)}; + state.create = make_constructor_create(); + state.create_at = make_constructor_create_at(); + state.is_invocable_with = make_constructor_is_invocable_with(); + state.arguments = make_constructor_arguments(); + return make_intrusive(std::move(state)); } } diff --git a/headers/meta.hpp/meta_states/destructor.hpp b/headers/meta.hpp/meta_states/destructor.hpp index 6630af4..941f63f 100644 --- a/headers/meta.hpp/meta_states/destructor.hpp +++ b/headers/meta.hpp/meta_states/destructor.hpp @@ -51,14 +51,16 @@ namespace meta_hpp::detail namespace meta_hpp::detail { + inline destructor_state::destructor_state(destructor_index nindex, metadata_map nmetadata) + : index{nindex} + , metadata{std::move(nmetadata)} {} + template < class_kind Class > destructor_state_ptr destructor_state::make(metadata_map metadata) { - return std::make_shared(destructor_state{ - .index{destructor_index::make()}, - .metadata{std::move(metadata)}, - .destroy{make_destructor_destroy()}, - .destroy_at{make_destructor_destroy_at()}, - }); + destructor_state state{destructor_index::make(), std::move(metadata)}; + state.destroy = make_destructor_destroy(); + state.destroy_at = make_destructor_destroy_at(); + return make_intrusive(std::move(state)); } } diff --git a/headers/meta.hpp/meta_states/evalue.hpp b/headers/meta.hpp/meta_states/evalue.hpp index f485d4f..a3f4f61 100644 --- a/headers/meta.hpp/meta_states/evalue.hpp +++ b/headers/meta.hpp/meta_states/evalue.hpp @@ -13,14 +13,16 @@ namespace meta_hpp::detail { + inline evalue_state::evalue_state(evalue_index nindex, metadata_map nmetadata) + : index{std::move(nindex)} + , metadata{std::move(nmetadata)} {} + template < enum_kind Enum > evalue_state_ptr evalue_state::make(std::string name, Enum evalue, metadata_map metadata) { - return std::make_shared(evalue_state{ - .index{evalue_index::make(std::move(name))}, - .metadata{std::move(metadata)}, - .enum_value{uvalue{evalue}}, - .underlying_value{uvalue{to_underlying(evalue)}}, - }); + evalue_state state{evalue_index::make(std::move(name)), std::move(metadata)}; + state.enum_value = uvalue{evalue}; + state.underlying_value = uvalue{to_underlying(evalue)}; + return make_intrusive(std::move(state)); } } diff --git a/headers/meta.hpp/meta_states/function.hpp b/headers/meta.hpp/meta_states/function.hpp index cf0c5cc..b7cebc1 100644 --- a/headers/meta.hpp/meta_states/function.hpp +++ b/headers/meta.hpp/meta_states/function.hpp @@ -110,15 +110,17 @@ namespace meta_hpp::detail namespace meta_hpp::detail { + inline function_state::function_state(function_index nindex, metadata_map nmetadata) + : index{std::move(nindex)} + , metadata{std::move(nmetadata)} {} + template < function_policy_kind Policy, function_kind Function > function_state_ptr function_state::make(std::string name, Function function, metadata_map metadata) { - return std::make_shared(function_state{ - .index{function_index::make(std::move(name))}, - .metadata{std::move(metadata)}, - .invoke{make_function_invoke(std::move(function))}, - .is_invocable_with{make_function_is_invocable_with()}, - .arguments{make_function_arguments()}, - }); + function_state state{function_index::make(std::move(name)), std::move(metadata)}; + state.invoke = make_function_invoke(std::move(function)); + state.is_invocable_with = make_function_is_invocable_with(); + state.arguments = make_function_arguments(); + return make_intrusive(std::move(state)); } } diff --git a/headers/meta.hpp/meta_states/member.hpp b/headers/meta.hpp/meta_states/member.hpp index cce6717..55dd0fb 100644 --- a/headers/meta.hpp/meta_states/member.hpp +++ b/headers/meta.hpp/meta_states/member.hpp @@ -146,16 +146,18 @@ namespace meta_hpp::detail namespace meta_hpp::detail { + inline member_state::member_state(member_index nindex, metadata_map nmetadata) + : index{std::move(nindex)} + , metadata{std::move(nmetadata)} {} + template < member_policy_kind Policy, member_kind Member > member_state_ptr member_state::make(std::string name, Member member, metadata_map metadata) { - return std::make_shared(member_state{ - .index{member_index::make(std::move(name))}, - .metadata{std::move(metadata)}, - .getter{make_member_getter(member)}, - .setter{make_member_setter(member)}, - .is_gettable_with{make_member_is_gettable_with()}, - .is_settable_with{make_member_is_settable_with()}, - }); + member_state state{member_index::make(std::move(name)), std::move(metadata)}; + state.getter = make_member_getter(member); + state.setter = make_member_setter(member); + state.is_gettable_with = make_member_is_gettable_with(); + state.is_settable_with = make_member_is_settable_with(); + return make_intrusive(std::move(state)); } } diff --git a/headers/meta.hpp/meta_states/method.hpp b/headers/meta.hpp/meta_states/method.hpp index dcd8a04..f73257a 100644 --- a/headers/meta.hpp/meta_states/method.hpp +++ b/headers/meta.hpp/meta_states/method.hpp @@ -121,15 +121,17 @@ namespace meta_hpp::detail namespace meta_hpp::detail { + inline method_state::method_state(method_index nindex, metadata_map nmetadata) + : index{std::move(nindex)} + , metadata{std::move(nmetadata)} {} + template < method_policy_kind Policy, method_kind Method > method_state_ptr method_state::make(std::string name, Method method, metadata_map metadata) { - return std::make_shared(method_state{ - .index{method_index::make(std::move(name))}, - .metadata{std::move(metadata)}, - .invoke{make_method_invoke(std::move(method))}, - .is_invocable_with{make_method_is_invocable_with()}, - .arguments{make_method_arguments()}, - }); + method_state state{method_index::make(std::move(name)), std::move(metadata)}; + state.invoke = make_method_invoke(std::move(method)); + state.is_invocable_with = make_method_is_invocable_with(); + state.arguments = make_method_arguments(); + return make_intrusive(std::move(state)); } } diff --git a/headers/meta.hpp/meta_states/scope.hpp b/headers/meta.hpp/meta_states/scope.hpp index e804ce4..0e5fc84 100644 --- a/headers/meta.hpp/meta_states/scope.hpp +++ b/headers/meta.hpp/meta_states/scope.hpp @@ -19,11 +19,13 @@ namespace meta_hpp::detail { + inline scope_state::scope_state(scope_index nindex, metadata_map nmetadata) + : index{std::move(nindex)} + , metadata{std::move(nmetadata)} {} + inline scope_state_ptr scope_state::make(std::string name, metadata_map metadata) { - return std::make_shared(scope_state{ - .index{scope_index::make(std::move(name))}, - .metadata{std::move(metadata)}, - }); + scope_state state{scope_index::make(std::move(name)), std::move(metadata)}; + return make_intrusive(std::move(state)); } } diff --git a/headers/meta.hpp/meta_states/variable.hpp b/headers/meta.hpp/meta_states/variable.hpp index b65e2e6..77df462 100644 --- a/headers/meta.hpp/meta_states/variable.hpp +++ b/headers/meta.hpp/meta_states/variable.hpp @@ -95,15 +95,17 @@ namespace meta_hpp::detail namespace meta_hpp::detail { + inline variable_state::variable_state(variable_index nindex, metadata_map nmetadata) + : index{std::move(nindex)} + , metadata{std::move(nmetadata)} {} + template < variable_policy_kind Policy, pointer_kind Pointer > variable_state_ptr variable_state::make(std::string name, Pointer pointer, metadata_map metadata) { - return std::make_shared(variable_state{ - .index{variable_index::make(std::move(name))}, - .metadata{std::move(metadata)}, - .getter{make_variable_getter(pointer)}, - .setter{make_variable_setter(pointer)}, - .is_settable_with{make_variable_is_settable_with()}, - }); + variable_state state{variable_index::make(std::move(name)), std::move(metadata)}; + state.getter = make_variable_getter(pointer); + state.setter = make_variable_setter(pointer); + state.is_settable_with = make_variable_is_settable_with(); + return make_intrusive(std::move(state)); } } diff --git a/headers/meta.hpp/meta_types.hpp b/headers/meta.hpp/meta_types.hpp index 2956028..a2870d9 100644 --- a/headers/meta.hpp/meta_types.hpp +++ b/headers/meta.hpp/meta_types.hpp @@ -542,11 +542,19 @@ namespace meta_hpp::detail const type_id id; const type_kind kind; - metadata_map metadata; + metadata_map metadata{}; explicit type_data_base(type_id nid, type_kind nkind) : id{nid} , kind{nkind} {} + + type_data_base(type_data_base&&) = delete; + type_data_base(const type_data_base&) = delete; + type_data_base& operator=(type_data_base&&) = delete; + type_data_base& operator=(const type_data_base&) = delete; + + protected: + ~type_data_base() = default; }; struct array_type_data final : type_data_base {