Service registry passed to a layout-source-provider builder so it can pull whatever registries / dependencies its factory needs. More...
#include <phosphor-layout-api/include/PhosphorLayoutApi/LayoutSourceProviderRegistry.h>
Public Member Functions | |
| template<typename T > | |
| bool | set (std::type_identity_t< T * > service) |
Register a service of type T. | |
| template<typename T > | |
| T * | get () const |
| Look up a previously-registered service. | |
Service registry passed to a layout-source-provider builder so it can pull whatever registries / dependencies its factory needs.
Composition roots populate one of these with every state object they own (typically the per-library I*Registry instances) keyed by the abstract interface type. Provider builders pull what they need by interface and ignore everything else; the type-erased get<T>() look-up is keyed on std::type_index so interfaces that the builder doesn't recognise are simply absent.
The context stores borrowed pointers — the composition root owns the lifetime. Pointers must outlive every produced ILayoutSourceFactory (which in practice means outlive the owning LayoutSourceBundle).
Type-safety of the void* round-trip: set<T> stores static_cast<void*>(T*) under key type_index(typeid(T)). The matching get<T> returns static_cast<T*>(void*) under the same key. Because std::type_index is unique per T and set/get always use the same T, the pointer round-trips without multi- inheritance offset drift — every get<T> returns the same adjusted T* that set<T> stored. Callers who set under one interface and get under a different one (e.g. the base class) simply miss (the keys differ → nullptr), avoiding UB.
Constraints on T (must hold for every interface used as a service key):
static_cast<void*>(T*) → static_cast<T*>(void*) round-trip assumes a fixed, vtable-independent offset between the derived object and its T subobject. Virtual inheritance makes that offset dynamic, and the void* detour silently discards it. Every interface in the PhosphorLayout provider chain (ILayoutSourceRegistry, IZoneLayoutRegistry, ITileAlgorithmRegistry, future IScrollingRegistry) is non-virtually inherited; preserve that when adding new services.std::type_index(typeid(T)) collapses const-qualification (and volatile), so set<const IFoo>(...) and get<IFoo>() resolve to the same slot. This is intentional — const doesn't change service identity — but it means you cannot register two distinct entries keyed by constness alone.
|
inline |
Look up a previously-registered service.
Returns nullptr when no matching service has been set — provider builders use this as the "composition root doesn't surface this engine, skip" signal by returning nullptr from their builder.
|
inline |
Register a service of type T.
T is intentionally non-deducible (wrapped in std::type_identity_t) so callers must spell the interface explicitly:
Without the non-deducing context, ctx.set(manager.get()) would deduce T from the concrete class and the registrar's ctx.get<IZoneLayoutRegistry>() would silently miss.
Duplicate registrations are a programmer error: asserts in debug, warns + ignores + returns false in release (first registration wins). Silent last-write-wins would let a typo in one composition root hand provider builders a different registry than the rest of the root is wired against, with no diagnostic. First-wins is the fail-safe release fallback — the original (presumably correct) registration stays authoritative; matches the single-shot discipline on LayoutSourceBundle::buildFromRegistered.
true on successful registration, false when a prior registration for T was already present. Callers that want hard-failure behaviour in release can wrap the call in their own assert; the default (discard-duplicate) is safe for composition roots that don't care.