From 5c3772e62e426237b4471a26591e4df295ad170a Mon Sep 17 00:00:00 2001 From: Roland Conybeare Date: Wed, 4 Feb 2026 16:23:55 -0500 Subject: [PATCH] xo-facet: + to_facet() convenience method on obj --- xo-facet/cmake/xo_facetConfig.cmake.in | 1 + xo-facet/include/xo/facet/FacetRegistry.hpp | 18 +++++++++++++++++- xo-facet/include/xo/facet/OObject.hpp | 4 ++++ .../include/xo/facet/facet_implementation.hpp | 8 ++++++++ xo-facet/include/xo/facet/obj.hpp | 10 ++++++++++ 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/xo-facet/cmake/xo_facetConfig.cmake.in b/xo-facet/cmake/xo_facetConfig.cmake.in index 88709824..23483949 100644 --- a/xo-facet/cmake/xo_facetConfig.cmake.in +++ b/xo-facet/cmake/xo_facetConfig.cmake.in @@ -2,6 +2,7 @@ include(CMakeFindDependencyMacro) # note: dependencies here must coordinate with xo-facet/CMakeLists.txt +find_dependency(xo_arena) find_dependency(xo_reflectutil) include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") check_required_components("@PROJECT_NAME@") diff --git a/xo-facet/include/xo/facet/FacetRegistry.hpp b/xo-facet/include/xo/facet/FacetRegistry.hpp index ad19cf53..d4b15188 100644 --- a/xo-facet/include/xo/facet/FacetRegistry.hpp +++ b/xo-facet/include/xo/facet/FacetRegistry.hpp @@ -236,9 +236,25 @@ namespace xo { /** runtime lookup table (AFacet,DRepr) -> impl **/ xo::map::DArenaHashMap registry_; - //std::unordered_map registry_; }; + // Deferred definitioon of obj::to_facet(), + // since implementation requires FacetRegistry + // + template + template + obj + obj::to_facet() + { + if constexpr (std::is_same_v) { + // return type has type-erased data + return FacetRegistry::instance().variant(*this); + } else { + // return type has known data + return obj(this->data()); + } + } + } /*namespace facet*/ } /*namespace xo*/ diff --git a/xo-facet/include/xo/facet/OObject.hpp b/xo-facet/include/xo/facet/OObject.hpp index e6eb0f6d..234a84df 100644 --- a/xo-facet/include/xo/facet/OObject.hpp +++ b/xo-facet/include/xo/facet/OObject.hpp @@ -59,6 +59,10 @@ namespace xo { **/ template struct OObject { + static_assert(has_facet_impl, + "Missing FacetImplementation specialization. " + "Did you include IFacet_DRepr.hpp (via the convenience header)?"); + using FacetType = AFacet; using ISpecific = FacetImplType; using DataType = DRepr; diff --git a/xo-facet/include/xo/facet/facet_implementation.hpp b/xo-facet/include/xo/facet/facet_implementation.hpp index 025645e8..7ce2ed5a 100644 --- a/xo-facet/include/xo/facet/facet_implementation.hpp +++ b/xo-facet/include/xo/facet/facet_implementation.hpp @@ -92,6 +92,14 @@ namespace xo { //static_assert(false && "expect specialization which should provide ImplType trait"); }; + /** true iff FacetImplementation has been specialized with ImplType. + * False when specialization header (IFacet_DRepr.hpp) not included. + **/ + template + concept has_facet_impl = requires { + typename FacetImplementation::ImplType; + }; + /** Retrieve facet implementation for a (facet,datatype) pair **/ template using FacetImplType = FacetImplementation::ImplType; diff --git a/xo-facet/include/xo/facet/obj.hpp b/xo-facet/include/xo/facet/obj.hpp index 850ef7bf..3619ae3e 100644 --- a/xo-facet/include/xo/facet/obj.hpp +++ b/xo-facet/include/xo/facet/obj.hpp @@ -6,6 +6,7 @@ #pragma once #include "RRouter.hpp" +//#include "FacetRegistry.hpp" // nope, would create include cycle #include #include @@ -127,6 +128,15 @@ namespace xo { return obj(iface, data); } + /** - runtime polymorphism (DRepr == DVariantPlaceholder) + * (requires FacetRegistry for lookup) + * - comptime polymorphism (DRepr != DVariantPlaceholder) + * + * Definition in FacetRegistry.hpp, to avoid #include dependency + **/ + template + obj to_facet(); + /** enabled when RRouter provides _preincrement. * Note we don't need this trick for comparison operators, * since return type is fixed.