Members of plugin::PluginCatalog<Base>.

std::unique_ptr<Base> create( key_type const& key );                    // (1)
std::unique_ptr<Base> create( key_type const& key, std::any const& config ); // (2)

Both take the catalog's shared lock, look key up, and — if found — invoke the stored Creator<Base>.

  1. Invokes Creator::operator()() — the default factory. Returns std::unique_ptr<Base>( creator() ), where creator() is new T().
  2. Invokes Creator::operator()(config) — the config factory.

Plugin<Base>::create is a thin wrapper over these: overload (2) there constructs the std::any from the caller's concrete type first.

Return value

std::unique_ptr<Base> owning the instance, or nullptr when key is not in the catalog.

Note a subtlety for overload (1): if the entry exists but has no default factory (registered config-only — not possible through the shipped macros, but possible via a hand-built Creator), Creator::operator()() returns nullptr and so does create.

Exceptions

ThrownWhen
std::runtime_error(2), entry has no config factory — message: "registered without config support".
std::bad_any_cast(2), config's stored type ≠ the registered Config.
(from T's ctor)propagated.

Example

auto& cat = Shape::catalog();

std::unique_ptr<Shape> a = cat.create( "Circle" );                    // Circle()
std::unique_ptr<Shape> b = cat.create( "Circle", std::any( Circle::Config{7} ) );
std::unique_ptr<Shape> c = cat.create( "Nope" );                      // nullptr

Prefer Shape::create("Circle", Circle::Config{7}) — it builds the std::any for you and is the documented surface.