/** @file obj.hpp * * @author Roland Conybeare, Dec 2025 **/ #pragma once #include "RRouter.hpp" namespace xo { namespace facet { /** object with borrowed state pointer * - With default Data argument: * type-erased polymorphic container * - with specific Data argument: * typed container. Trivially de-virtualizable * * Example: * std::unique_ptr z1_in * = std::make_unique(1.0, 0.0): * ubox z1{z1_in.release()}; * z1.xcoord(); * * * +-----+ +-----------------+ * Interface | x-------------->| vtable for | * +-----+ | some descendant | * Data | x--------\ | of AInterface | * +-----+ | | | * | +-----------------+ * | * | +--------------+ * \----->| data :: Repr | * +--------------+ * * Binary representation of unay * is compatible for different values of @tparam Data * as long as vtable pointer moves along with data pointer. * * In particular binary representation for * ubox is as if it inherited ubox * (even though it does not as far as compiler is concerned) * * This is load-bearing for @ref move2any see below **/ template struct obj : public RoutingType> { using Super = RoutingType>; obj() {} explicit obj(Super::DataPtr d) : Super(d) {} /** copy constructor **/ template obj(const obj & other) requires (std::is_same_v || std::is_convertible_v) : Super() { if constexpr (std::is_convertible_v) { this->data_ = other.data_; } else { this->from_data(other.data_); } } /** move constructor from a different representation. * allowed given: * - same abstract interface * - same strategy for holding state (naked / unique / refcounted ...) **/ template obj(const obj && other) requires (std::is_same_v || std::is_convertible_v) : Super() { static_assert(sizeof(obj) == sizeof(obj)); other.move2any(this); assert(other.data_ = nullptr); } /** safe downcast from variant. null if downcast fails **/ static obj from(const OObject & other) { return obj(other.template downcast()); } }; /** Use: * auto o = with_facet::obj(&data); **/ template struct with_facet { template static obj mkobj(DRepr * data) { obj x(data); return x; } }; #ifdef DEPRECATED template inline obj with_facet(DRepr * data) { return obj(data); } #endif } /*namespace facet*/ using facet::obj; } /*namespace xo*/ /* end obj.hpp */