Defined in <plugin/PluginCatalog.hh> (CREATECATALOG) and <plugin/Plugin.hh> (CATALOG).

CREATECATALOG

#define CREATECATALOG( BASE )                                       \
  template<>                                                        \
  plugin::PluginCatalog< BASE >& plugin::Plugin< BASE >::catalog( ) \
  {                                                                 \
    static plugin::PluginCatalog< BASE > internalCatalog;           \
    return internalCatalog;                                         \
  }

Provides the definition of Plugin<BASE>::catalog() — an explicit specialisation returning a function-local static. Put it in exactly one translation unit, which the host links:

// Shape.cpp  (host)
#include "Shape.hh"
#include <plugin/PluginCatalog.hh>

CREATECATALOG( Shape );

Why exactly one, in the host

  • More than one definition → ODR violation / duplicate-symbol link error.
  • In a plugin instead of the host → with RTLD_GLOBAL the first DSO's catalog wins and things mostly work by luck; with RTLD_LOCAL each DSO gets its own catalog and the host sees no registrations. Put it in the host.
  • Missing entirely → link error: undefined reference to plugin::Plugin<Shape>::catalog().

Because it is one function-local static reached through one specialisation, every REGISTER in every loaded DSO and every Shape::create call resolve to the same object (the loader uses RTLD_GLOBAL so the symbol is shared).

CATALOG

#define CATALOG( BASE ) plugin::Plugin< BASE >::catalog( )

A shorthand. CATALOG(Shape)plugin::Plugin<Shape>::catalog()Shape::catalog().

std::cout << CATALOG(Shape).size() << " shape plugins\n";
for( auto const& n : CATALOG(Shape).names(true) ) std::cout << "  " << n << '\n';

Use whichever form reads best; they are identical.