Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
PhosphorLayout::FactoryContext Class Reference

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.
 

Detailed Description

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):

  • Non-virtual inheritance only. The 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.
  • Top-level cv is stripped. 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.

Member Function Documentation

◆ get()

template<typename T >
T * PhosphorLayout::FactoryContext::get ( ) const
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.

◆ set()

template<typename T >
bool PhosphorLayout::FactoryContext::set ( std::type_identity_t< T * >  service)
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:

ctx.set<IZoneLayoutRegistry>(manager.get()); // keyed by the interface

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.

Returns
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.

The documentation for this class was generated from the following file: