diff --git a/src/lib/diff/tree-diff-mutator-binding.cpp b/src/lib/diff/tree-diff-mutator-binding.cpp index b1edc5533..123244b9f 100644 --- a/src/lib/diff/tree-diff-mutator-binding.cpp +++ b/src/lib/diff/tree-diff-mutator-binding.cpp @@ -48,7 +48,9 @@ namespace lib { namespace diff{ - ScopeManager::~ScopeManager() { }; ///< emit VTable here... + TreeMutator::~TreeMutator() { } ///< emit VTables here... + + ScopeManager::~ScopeManager() { }; diff --git a/src/lib/diff/tree-mutator.hpp b/src/lib/diff/tree-mutator.hpp index 4d5ebad02..822a7bebf 100644 --- a/src/lib/diff/tree-mutator.hpp +++ b/src/lib/diff/tree-mutator.hpp @@ -107,63 +107,6 @@ namespace lib { - /////////////////////////////TODO move over into opaque-holder.hpp - /** - * handle to allow for safe _»remote implantation«_ - * of an unknown subclass into a given opaque InPlaceBuffer, - * without having to disclose the concrete buffer type or size. - * @remarks this is especially geared towards use in APIs, allowing - * a not yet known implementation to implant an agent or collaboration - * partner into the likewise undisclosed innards of the exposed service. - * @warning the type BA must expose a virtual dtor, since the targeted - * InPlaceBuffer has to take ownership of the implanted object. - */ - template - class PlantingHandle - { - void* buffer_; - size_t maxSiz_; - - ///////TODO static assert to virtual dtor?? - public: - template - PlantingHandle (InPlaceBuffer& targetBuffer) - : buffer_(&targetBuffer) - , maxSiz_(maxSiz) - { } - - - template - BA& - create (SUB&& subMutator) - { - if (sizeof(SUB) > maxSiz_) - throw error::Fatal("Unable to implant implementation object of size " - "exceeding the pre-established storage buffer capacity." - ,error::LUMIERA_ERROR_CAPACITY); - - using Holder = InPlaceBuffer; - Holder& holder = *static_cast (buffer_); - - return holder.create (std::forward (subMutator)); - } - - template - bool - canCreate() const - { - return sizeof(SUB) <= maxSiz_; - } - - BA* - get() const - { - ENSURE (buffer_); - BA& bufferContent = **static_cast*> (buffer_); - return &bufferContent; - } - }; - /////////////////////////////TODO move over into opaque-holder.hpp namespace diff{ namespace error = lumiera::error; @@ -199,6 +142,8 @@ namespace diff{ { public: + virtual ~TreeMutator(); ///< this is an interface + /** only allow default and move construction */ TreeMutator () =default; TreeMutator (TreeMutator&&) =default; diff --git a/src/lib/opaque-holder.hpp b/src/lib/opaque-holder.hpp index 750f39483..799703ce7 100644 --- a/src/lib/opaque-holder.hpp +++ b/src/lib/opaque-holder.hpp @@ -571,6 +571,12 @@ namespace lib { * and especially it is mandatory for the base class to provide a * virtual dtor. On the other hand, just the (alignment rounded) * storage for the object(s) placed into the buffer is required. + * @remarks as a complement, PlantingHandle may be used on APIs to offer + * a lightweight way for clients to provide a callback. + * @warning InPlaceBuffer really takes ownership, and even creates a + * default constructed instance of the base class right away. + * Yet the requirement for a virtual dtor is deliberately not + * enforced here, to allow use for types without VTable. * * @tparam BA the nominal Base/Interface class for a family of types * @tparam siz maximum storage required for the targets to be held inline @@ -669,6 +675,67 @@ namespace lib { + /** + * handle to allow for safe _»remote implantation«_ + * of an unknown subclass into a given opaque InPlaceBuffer, + * without having to disclose the concrete buffer type or size. + * @remarks this is especially geared towards use in APIs, allowing + * a not yet known implementation to implant an agent or collaboration + * partner into the likewise undisclosed innards of the exposed service. + * @warning the type BA must expose a virtual dtor, since the targeted + * InPlaceBuffer has to take ownership of the implanted object. + */ + template + class PlantingHandle + { + void* buffer_; + size_t maxSiz_; + + static_assert (std::has_virtual_destructor(), + "target interface BA must provide virtual dtor, " + "since InPlaceBuffer needs to take ownership."); + + public: + template + PlantingHandle (InPlaceBuffer& targetBuffer) + : buffer_(&targetBuffer) + , maxSiz_(maxSiz) + { } + + + template + BA& + create (SUB&& implementation) + { + if (sizeof(SUB) > maxSiz_) + throw error::Fatal("Unable to implant implementation object of size " + "exceeding the pre-established storage buffer capacity." + ,error::LUMIERA_ERROR_CAPACITY); + + using Holder = InPlaceBuffer; + Holder& holder = *static_cast (buffer_); + + return holder.create (std::forward (implementation)); + } + + template + bool + canCreate() const + { + return sizeof(SUB) <= maxSiz_; + } + + BA* + get() const + { + ENSURE (buffer_); + BA& bufferContent = **static_cast*> (buffer_); + return &bufferContent; + } + }; + + + } // namespace lib #endif