xo-facet: runtime facet lookup [PROTO]
This commit is contained in:
parent
b1ec26a9fd
commit
fe4fc4a28d
5 changed files with 86 additions and 3 deletions
|
|
@ -10,6 +10,8 @@ Library dependency tower for *xo-facet*:
|
|||
+-----------------+
|
||||
| xo_facet |
|
||||
+-----------------+
|
||||
| xo_arena |
|
||||
+-----------------+
|
||||
| xo_cmake |
|
||||
+-----------------+
|
||||
|
||||
|
|
@ -18,6 +20,8 @@ Abstraction tower for *xo-facet* components.
|
|||
.. ditaa::
|
||||
:--scale: 0.85
|
||||
|
||||
+--------------------------------+
|
||||
| FacetRegistry |
|
||||
+--------------------------------+
|
||||
| obj(A,D) |
|
||||
+--------------------------------+
|
||||
|
|
@ -37,9 +41,12 @@ Abstraction tower for *xo-facet* components.
|
|||
* - Component
|
||||
- Use
|
||||
- Description
|
||||
* - ``FacetRegistry``
|
||||
- ``FacetRegistry::convert_to<ATo>(obj<AFrom>)``
|
||||
- polymorphic conversion between facets
|
||||
* - ``obj<A,D>``
|
||||
- ``x.foo()``
|
||||
- convenience wrapper with interface A, with state D*
|
||||
- convenience wrapper for interface A, with state D*
|
||||
* - ``RRouter<A,D>``
|
||||
- ``x.foo()``
|
||||
- auto injects data pointer
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ This gives us several benefits:
|
|||
simpler that the pathway for a data pointer. This increases scope for
|
||||
devirtualization.
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: xo-facet contents
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "facet_implementation.hpp"
|
||||
#include "typeseq.hpp"
|
||||
#include "obj.hpp"
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
|
|
@ -88,7 +89,8 @@ namespace xo {
|
|||
bool contains(typeseq facet_id,
|
||||
typeseq repr_id) const
|
||||
{
|
||||
return registry_.find(key_type(facet_id, repr_id)) != registry_.end();
|
||||
return (registry_.find(key_type(facet_id, repr_id))
|
||||
!= registry_.end());
|
||||
}
|
||||
|
||||
/** Type-safe lookup
|
||||
|
|
@ -99,7 +101,37 @@ namespace xo {
|
|||
**/
|
||||
template <typename AFacet>
|
||||
const AFacet * lookup(typeseq repr_id) const {
|
||||
return static_cast<const AFacet *>(this->_lookup(typeseq::id<AFacet>(), repr_id));
|
||||
return static_cast<const AFacet *>
|
||||
(this->_lookup(typeseq::id<AFacet>(), repr_id));
|
||||
}
|
||||
|
||||
/** Runtime polymorphism:
|
||||
* Switch @param from from interface @tp AFrom to interface @tp ATo.
|
||||
*
|
||||
* Use:
|
||||
* obj<AFoo> foo
|
||||
* = ...; // Foo instance with variant impl
|
||||
* obj<ABar> bar
|
||||
* = FacetRegistry::variant<ABar,AFoo>(foo);
|
||||
**/
|
||||
template <typename ATo, typename AFrom>
|
||||
obj<ATo> variant(obj<AFrom> from) {
|
||||
return variant<ATo>(from._typeseq(), from.data());
|
||||
}
|
||||
|
||||
/** Runtime polymorphism:
|
||||
* Create variant from representation @p data
|
||||
* with actual type @p repr_id.
|
||||
*
|
||||
* Use:
|
||||
* obj<AFoo> foo = ...; // Foo instance with variant impl
|
||||
* obj<ABar> bar
|
||||
* = FacetRegistry::variant<ABar>(foo._typeseq(), foo.opaque_data());
|
||||
**/
|
||||
template <typename AFacet>
|
||||
obj<AFacet> variant(typeseq repr_id, void * data) {
|
||||
const AFacet * iface = this->lookup<AFacet>(repr_id);
|
||||
return obj<AFacet>::variant(iface, data);;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -134,6 +166,7 @@ namespace xo {
|
|||
private:
|
||||
FacetRegistry() = default;
|
||||
|
||||
/** runtime lookup table (AFacet,DRepr) -> impl **/
|
||||
std::unordered_map<key_type, const void *, KeyHash> registry_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,22 @@ namespace xo {
|
|||
memcpy(&(iface_[0]), (void*)&tmp, sizeof(ISpecific));
|
||||
}
|
||||
|
||||
/**
|
||||
* Runtime polymorphism:
|
||||
* Create variant for specific interface @p impl
|
||||
* with type-erased data @p data.
|
||||
*
|
||||
* Implements
|
||||
* obj<AFacet>::variant(iface, data)
|
||||
**/
|
||||
OObject(const AFacet * impl, void * data)
|
||||
requires std::is_same_v<DRepr, DVariantPlaceholder>
|
||||
: data_{reinterpret_cast<DVariantPlaceholder*>(data)}
|
||||
{
|
||||
static_assert(sizeof(ISpecific) == sizeof(impl));
|
||||
memcpy(&(iface_[0]), (void*)impl, sizeof(ISpecific));
|
||||
}
|
||||
|
||||
OObject(const OObject & oother) {
|
||||
_launder_from(oother);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,18 @@ namespace xo {
|
|||
|
||||
obj(const obj & rhs) = default;
|
||||
|
||||
/** Runtime polymorphism:
|
||||
* assemble variant from specific interface @p iface
|
||||
* and type-erased representation @p data.
|
||||
*
|
||||
* Implements
|
||||
* obj<AFacet>::variant(iface, data)
|
||||
**/
|
||||
obj(const AFacet * iface, void * data)
|
||||
requires std::is_same_v<DRepr, DVariantPlaceholder>
|
||||
: Super(iface, data)
|
||||
{}
|
||||
|
||||
/** pseudo copy constructor
|
||||
*
|
||||
* Intended for use cases:
|
||||
|
|
@ -96,6 +108,20 @@ namespace xo {
|
|||
return obj(other.template downcast<DRepr>());
|
||||
}
|
||||
|
||||
/** Runtime polymorphism.
|
||||
* Create variant given interface @p iface,
|
||||
* type-erased represention @p data
|
||||
*
|
||||
* Use:
|
||||
* AFoo * impl = ....;
|
||||
* auto x = obj<AFoo>::variant(impl, data)
|
||||
**/
|
||||
static obj variant(const AFacet * iface, void * data)
|
||||
requires std::is_same_v<DRepr, DVariantPlaceholder>
|
||||
{
|
||||
return obj(iface, data);
|
||||
}
|
||||
|
||||
/** enabled when RRouter<AFacet> provides _preincrement.
|
||||
* Note we don't need this trick for comparison operators,
|
||||
* since return type is fixed.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue