diff --git a/include/xo/facet/OUniqueBox.hpp b/include/xo/facet/OUniqueBox.hpp deleted file mode 100644 index d22ad70..0000000 --- a/include/xo/facet/OUniqueBox.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/** @file OUniqueBox.hpp - * - * @author Roland Conybeare, Dec 2025 - **/ - -namespace xo { - namespace facet { - /** - * Uniquely-owned instance with runtime polymorphism. - * - * Reminder that in the facet object model we expect - * objects to be transient. - * - - * - * Unlike OUniqueBox can use for variant data - * without additional overhead. Tradeoff is that avoiding such - * overhead excludes std::unique_ptr. - * - * We're going to instead rely on AInterface providing a destruct_data() method, - * so in practice get the deleter from interface state. - * - * Possibly means we need all abstract interfaces to share a common base - * - * Remarks: - * - when @tparam Data is supplied - **/ - template - struct OUniqueBox { - using AbstractInterface = AInterface; - using ISpecific = ISpecificFor::ImplType; - /* note: Data can be void here */ - using DataType = Data; - using DataBox = Data*; - - explicit OUniqueBox() {} - /* unsatisfactory b/c doesn't enforce that @p d is heap-allocated */ - explicit OUniqueBox(DataBox d) : data_{std::move(d)} {} - - ~OUniqueBox() { - if (data_ != nullptr) { - this->iface()->destruct_data(data_); - delete data_; - this->data_ = nullptr; - } - } - - const AInterface * iface() const - requires std::is_same_v - { - return std::launder(&iface_); - } - - const AInterface * iface() const - requires (!std::is_same_v) - { - return &iface_; - } - - /** note: would prefer this to be constexpr, but not simple asof gcc 14.3 **/ - static bool _valid; - - /** note: load-bearing for routing classes such as RComplex **/ - Data * data() const { return data_; } - - ISpecific iface_; - DataBox data_ = nullptr; - }; - - - } -} /*namespace xo*/ - -/* end OUniqueBox.hpp */ diff --git a/include/xo/facet/box.hpp b/include/xo/facet/box.hpp new file mode 100644 index 0000000..25a6561 --- /dev/null +++ b/include/xo/facet/box.hpp @@ -0,0 +1,83 @@ +/** @file box.hpp + * + * @author Roland Conybeare, Jan 2026 + **/ + +#pragma once + +#include "obj.hpp" + +namespace xo { + namespace facet { + + /** object with owned state + * - with default DRepr argument: + * type-erased container (runtime polymorphism). + * - with sepcific DRepr argument: + * typed container (comptime polymorphism). + **/ + template + struct box : public RoutingType> { + using Super = RoutingType>; + + box() : Super() {} + + /** box takes ownership of data @p *d; + * will destroy when box goes out of scope. + * + * Note this is not useful when DRepr=DVariablePlaceholder + **/ + explicit box(Super::DataPtr d) : Super(d) {} + + /** Adopt instance that has interface @p iface and (type-erased here) + * representation @p data + **/ + box(const AFacet * iface, void * data) + requires std::is_same_v + : Super(iface, data) + {} + + /** (copy ctor not supported -- ownership is unique) **/ + + // -------------------------------- + + /** Move constructor **/ + template + box(box && other) + requires (std::is_same_v + || std::is_same_v) + : obj() + { + /* replacing .iface_ along w/ .data_ */ + this->from_obj(other); + + other.reset_opaque(nullptr); + } + + /** explicit conversion to obj **/ + obj to_op() const noexcept { return obj(this->iface(), this->data()); } + + /** Take ownership from unowned object **/ + template + box & adopt(const obj & other) + requires (std::is_same_v + || std::is_same_v) + { + /* replace .iface_ along w/ .data_ */ + this->from_obj(other); + + return *this; + } + + ~box() { + auto p = this->data(); + this->_drop(); + ::operator delete(p); + } + }; + } /*namespace facet*/ + + using facet::box; +} /*namespace xo*/ + +/* end box.hpp */ diff --git a/include/xo/facet/obj.hpp b/include/xo/facet/obj.hpp index 3983cec..850ef7b 100644 --- a/include/xo/facet/obj.hpp +++ b/include/xo/facet/obj.hpp @@ -12,9 +12,9 @@ namespace xo { namespace facet { /** object with borrowed state pointer - * - With default Data argument: + * - With default DRepr argument: * type-erased polymorphic container - * - with specific Data argument: + * - with specific DRepr argument: * typed container. Trivially de-virtualizable * * Example: @@ -88,7 +88,7 @@ namespace xo { * - same strategy for holding state (naked / unique / refcounted ...) **/ template - obj(const obj && other) + obj(obj && other) requires (std::is_same_v || std::is_convertible_v) : Super() @@ -98,7 +98,7 @@ namespace xo { } obj & operator=(const obj & rhs) { - /* ensure we replace .iface_ along w/ .ata_ */ + /* ensure we replace .iface_ along w/ .data_ */ this->from_obj(rhs); return *this; }