namespace plugin {
template< class Base >
class PluginCatalog;
}
Defined in <plugin/PluginCatalog.hh>.
One PluginCatalog<Base> exists per plugin hierarchy. It maps a std::string key to a Creator<Base> and is safe to read and mutate concurrently.
Member types
| Type | Definition |
|---|---|
key_type | std::string |
mapped_type | Creator<Base> |
container_type | std::map<key_type, mapped_type, std::less<key_type>> |
Member functions
| Group | Functions | Lock | Page |
|---|---|---|---|
| mutators | insert, erase | exclusive | insert, erase |
| create | create(key), create(key, std::any) | shared | create |
| observers | names, contains, empty, size | shared | names, contains, size |
Copy and move are provided and lock both operands (std::scoped_lock / std::lock with a deferred shared_lock), but a catalog is almost always a singleton reached through CREATECATALOG and never copied in practice.
Thread safety
A mutable std::shared_mutex guards entries_:
create,contains,empty,size,namestake a shared (read) lock — they run concurrently with each other.insert,erasetake an exclusive (write) lock.
Registration (insert) happens during DSO static initialisation, which is single-threaded, so writes rarely contend with anything.
Direct use
You normally go through Plugin<Base>::create, but the catalog is a plain object:
auto& cat = Shape::catalog(); // PluginCatalog<Shape>&
cat.size(); // how many keys (aliases excluded from names())
cat.contains( "Circle" );
auto up = cat.create( "Circle" ); // std::unique_ptr<Shape>, or nullptr
insert / erase are public but are the registration macros' job — calling them by hand is for tests or a host that builds a plugin in-process without a DSO.

