diff --git a/include/xo/reflect/EstablishTypeDescr.hpp b/include/xo/reflect/EstablishTypeDescr.hpp index 423345d..0f18d84 100644 --- a/include/xo/reflect/EstablishTypeDescr.hpp +++ b/include/xo/reflect/EstablishTypeDescr.hpp @@ -41,7 +41,8 @@ namespace xo { static TypeDescrW establish() { TypeDescrW td = TypeDescrBase::require(&typeid(T), std::string(type_name()), - nullptr); + nullptr /*tdextra*/, + nullptr /*invoker*/); #ifdef NOT_USING std::function to_self_tp; diff --git a/include/xo/reflect/Object.hpp b/include/xo/reflect/Object.hpp index fc7f160..91a5ced 100644 --- a/include/xo/reflect/Object.hpp +++ b/include/xo/reflect/Object.hpp @@ -21,8 +21,6 @@ namespace xo { **/ class Object : public reflect::SelfTagging { public: - using TypeId = xo::reflect::TypeId; - Object(TypeId type_id) : type_id_{type_id} {} private: diff --git a/include/xo/reflect/Reflect.hpp b/include/xo/reflect/Reflect.hpp index 23179c1..d4cfd34 100644 --- a/include/xo/reflect/Reflect.hpp +++ b/include/xo/reflect/Reflect.hpp @@ -36,7 +36,7 @@ namespace xo { // ----- xo::ref::rp ----- template - class EstablishTdx> { + class EstablishTdx> { public: /* definition provide after decl for Reflect {} below */ static std::unique_ptr make(); @@ -182,9 +182,12 @@ namespace xo { } else { /* control comes here the first time require() runs */ + static detail::InvokerAux s_final_invoker; + auto final_tdx = EstablishTdx::make(); - retval_td->assign_tdextra(std::move(final_tdx)); + retval_td->assign_tdextra(&s_final_invoker, + std::move(final_tdx)); /* also need to require for each child */ } @@ -274,7 +277,7 @@ namespace xo { */ template std::unique_ptr - EstablishTdx>::make() { + EstablishTdx>::make() { /* need to ensure Object is property reflected. * * In practice must be a class type, since has to store refcount @@ -282,7 +285,7 @@ namespace xo { */ Reflect::require(); - return RefPointerTdx>::make(); + return RefPointerTdx>::make(); } /*make*/ // ----- std::array ----- diff --git a/include/xo/reflect/StructReflector.hpp b/include/xo/reflect/StructReflector.hpp index 220990a..b443950 100644 --- a/include/xo/reflect/StructReflector.hpp +++ b/include/xo/reflect/StructReflector.hpp @@ -80,11 +80,14 @@ namespace xo { return SelfTagger::self_tp(object); }); + static detail::InvokerAux s_final_invoker; + auto tdx = StructTdx::make(std::move(this->member_v_), have_to_self_tp, to_self_tp_fn); - this->td_->assign_tdextra(std::move(tdx)); + this->td_->assign_tdextra(&s_final_invoker, + std::move(tdx)); } } /*complete*/ diff --git a/include/xo/reflect/TypeDescr.hpp b/include/xo/reflect/TypeDescr.hpp index 95d9364..53247ad 100644 --- a/include/xo/reflect/TypeDescr.hpp +++ b/include/xo/reflect/TypeDescr.hpp @@ -88,6 +88,33 @@ namespace xo { /* native type_info object for encapsulated type */ std::type_info const * tinfo_ = nullptr; }; /*TypeInfoRef*/ + + namespace detail { + struct Invoker { + virtual void dtor(void * addr) const = 0; + }; + + /** Auxiliary template for capturing destructor for type T, + * if it has one. + * + * Example + * T * p = new T(...); + * DestructorAux::dtor(p); + **/ + template + struct InvokerAux : public Invoker { + virtual void dtor(void * addr) const override { + T * obj = static_cast(addr); + + obj->~T(); + } + }; + + template<> + struct InvokerAux : public Invoker { + virtual void dtor(void *) const override {} + }; + } /*namespace detail*/ } /*namespace reflect*/ } /*namespace xo*/ @@ -191,6 +218,7 @@ namespace xo { */ static TypeDescrW require(const std::type_info * tinfo, const std::string & canonical_name, + detail::Invoker * invoker, std::unique_ptr tdextra); /** Create type-description for function from input ingredients. **/ @@ -364,16 +392,21 @@ namespace xo { /* call this once to attach extended type information to a type-description * (e.g. description of struct members for a record type) */ - void assign_tdextra(std::unique_ptr tdx) { + void assign_tdextra(detail::Invoker * invoker, + std::unique_ptr tdx) { this->complete_flag_ = true; + this->invoker_ = invoker; this->tdextra_ = std::move(tdx); } + // ----- actions ----- + private: TypeDescrBase(TypeId id, const std::type_info * tinfo, const std::string & canonical_name, - std::unique_ptr tdextra); + std::unique_ptr tdextra, + detail::Invoker * invoker); void assign_native_tinfo(const std::type_info * tinfo) { assert(!native_typeinfo_); @@ -429,8 +462,9 @@ namespace xo { static std::unordered_map s_function_type_map; private: - /* unique id# for this type */ + /** unique id# for this type **/ TypeId id_; + /** typeinfo for type T, if available. nullptr otherwise. * * 1. Always available for type-descriptions constructed via Reflect::require. @@ -438,6 +472,7 @@ namespace xo { * see Lambda.cpp in xo-expression. **/ std::type_info const * native_typeinfo_ = nullptr; + /** canonical name for this type (see demangle.hpp for type_name()) * e.g. * xo::option::Px2 @@ -448,19 +483,28 @@ namespace xo { * so need to use std::string here **/ std::string canonical_name_; + /** substring .canonical_name, just after last ':' * e.g. * Px2 **/ std::string_view short_name_; - /* set to true once final value for .tdextra is established + + /** set to true once final value for .tdextra is established * intially all TypeDescr objects will use AtomicTdx for .tdextra * Reflect::require() upgrades .tdextra for particular types. * When that procedure makes a decision for a type T, * .complete_flag will be set to true for the corresponding TypeDescrBase instance - */ + **/ bool complete_flag_ = false; - /* additional type information that either: + + /** capture basic instance-management operations for this type. + * Given an instance T x: + * - invoker_->dtor(&x) invokes T::~T() + **/ + detail::Invoker * invoker_; + + /** additional type information that either: * (a) isn't universal across all types, * e.g. dereferencing instance of a pointer type * (b) can't be captured with template-fu, @@ -469,7 +513,7 @@ namespace xo { * generally .tdextra will be populated some time after TypeDescrBase's ctor exits. * This is necessary because of (b) above, also because of possibility of recursive * types. - */ + **/ std::unique_ptr tdextra_; }; /*TypeDescrBase*/ diff --git a/src/reflect/TypeDescr.cpp b/src/reflect/TypeDescr.cpp index 4d9e3d5..4d04801 100644 --- a/src/reflect/TypeDescr.cpp +++ b/src/reflect/TypeDescr.cpp @@ -54,6 +54,7 @@ namespace xo { TypeDescrW TypeDescrBase::require(const std::type_info * native_tinfo, const std::string & canonical_name, + detail::Invoker * invoker, std::unique_ptr tdextra) { if (native_tinfo) { @@ -152,7 +153,8 @@ namespace xo { auto new_td = new TypeDescrBase(new_td_id, native_tinfo, canonical_name, - std::move(tdextra)); + std::move(tdextra), + invoker); new_slot.reset(new_td); @@ -178,6 +180,7 @@ namespace xo { return require(nullptr /*native_tinfo - n/avail on this path*/, fn_info.make_canonical_name(), + nullptr /*invoker*/, std::move(fn_tdextra)); } /*require_by_fn_info*/ @@ -240,11 +243,13 @@ namespace xo { TypeDescrBase::TypeDescrBase(TypeId id, const std::type_info * native_tinfo, const std::string & canonical_name, - std::unique_ptr tdextra) + std::unique_ptr tdextra, + detail::Invoker * invoker) : id_{std::move(id)}, native_typeinfo_{native_tinfo}, canonical_name_{std::move(canonical_name)}, short_name_{unqualified_name(canonical_name_)}, + invoker_{invoker}, tdextra_{std::move(tdextra)} { } diff --git a/utest/CMakeLists.txt b/utest/CMakeLists.txt index edc997e..535907a 100644 --- a/utest/CMakeLists.txt +++ b/utest/CMakeLists.txt @@ -9,10 +9,6 @@ set(SELF_SOURCE_FILES FunctionTdx.test.cpp) xo_add_utest_executable(${SELF_EXECUTABLE_NAME} ${SELF_SOURCE_FILES}) - -# ---------------------------------------------------------------- -# deps: indentlog, .. - xo_self_dependency(${SELF_EXECUTABLE_NAME} reflect) xo_external_target_dependency(${SELF_EXECUTABLE_NAME} Catch2 Catch2::Catch2)