/** @file FacetRegistry.hpp * * @brief Runtime facet implementation lookup * * @author Roland Conybeare, Jan 2026 **/ #pragma once #include "facet_implementation.hpp" #include "typeseq.hpp" #include "obj.hpp" #include #include namespace xo { namespace facet { /** @class FacetRegistry * * @brief Runtime registry for facet implementations * * Enables late-binding between facets. For example, given an * obj with unknown concrete type at compile time, * look up the APrintable implementation at runtime. * * Example: * // Registration (at initialization time) * FacetRegistry::instance().register_impl(); * FacetRegistry::instance().register_impl(); * * // Lookup (at runtime) * typeseq repr_id = obj->_typeseq(); * const APrintable* printable = runtime_impl_for(repr_id); * printable->print(obj.data(), out); **/ class FacetRegistry { public: using key_type = std::pair; /** hash function for key_type **/ struct KeyHash { std::size_t operator()(const key_type & k) const noexcept { // combine the two seqno values std::size_t h1 = std::hash{}(k.first.seqno()); std::size_t h2 = std::hash{}(k.second.seqno()); return h1 ^ (h2 << 1); } }; /** singleton instance **/ static FacetRegistry & instance() { static FacetRegistry s_instance; return s_instance; } /** Type-safe registration * * Registers the compile-time FacetImplementation * for runtime lookup. * * @tparam AFacet abstract facet type * @tparam DRepr data representation type **/ template static void register_impl() { static FacetImplType impl; instance()._register_impl(typeseq::id(), typeseq::id(), &impl); } /** Convenience function for runtime lookup * * @tparam AFacet abstract facet type * @param repr_id typeseq for data representation * @return pointer to AFacet implementation, or nullptr **/ template static inline const AFacet * impl_for(typeseq repr_id) { return FacetRegistry::instance().lookup(repr_id); } /** Number of registered (facet, repr) pairs **/ std::size_t size() const { return registry_.size(); } /** Check if implementation is registered **/ bool contains(typeseq facet_id, typeseq repr_id) const { return (registry_.find(key_type(facet_id, repr_id)) != registry_.end()); } /** Type-safe lookup * * @tparam AFacet abstract facet type * @param repr_id typeseq for data representation * @return pointer to AFacet implementation, or nullptr **/ template const AFacet * lookup(typeseq repr_id) const { return static_cast (this->_lookup(typeseq::id(), repr_id)); } /** Runtime polymorphism: * Switch @param from from interface @tp AFrom to interface @tp ATo. * * Use: * obj foo * = ...; // Foo instance with variant impl * obj bar * = FacetRegistry::variant(foo); **/ template obj variant(obj from) { return variant(from._typeseq(), from.data()); } /** Runtime polymorphism: * Create variant from representation @p data * with actual type @p repr_id. * * Use: * obj foo = ...; // Foo instance with variant impl * obj bar * = FacetRegistry::variant(foo._typeseq(), foo.opaque_data()); **/ template obj variant(typeseq repr_id, void * data) { const AFacet * iface = this->lookup(repr_id); return obj::variant(iface, data);; } private: /** Register a facet implementation (type-erased) * * @param facet_id typeseq for abstract facet (e.g., APrintable) * @param repr_id typeseq for data representation (e.g., DFloat) * @param impl pointer to stateless implementation instance **/ void _register_impl(typeseq facet_id, typeseq repr_id, const void * impl) { registry_[key_type(facet_id, repr_id)] = impl; } /** Lookup facet implementation (type-erased) * * @return pointer to implementation, or nullptr if not registered **/ const void * _lookup(typeseq facet_id, typeseq repr_id) const { auto ix = registry_.find(key_type(facet_id, repr_id)); if (ix == registry_.end()) return nullptr; else return ix->second; } private: FacetRegistry() = default; /** runtime lookup table (AFacet,DRepr) -> impl **/ std::unordered_map registry_; }; } /*namespace facet*/ } /*namespace xo*/ /* end FacetRegistry.hpp */