Code View

plugin / plugin-2.2.0.0 / src / plugin / Plugin.hh
// SPDX-License-Identifier: MIT
#pragma once

#include <dso/DSOLoader.hh>
#include <plugin/PluginCatalog.hh>

#include <any>
#include <memory>
#include <string>

namespace plugin
{
  /**
   * @brief Base class template for the plugin system.
   *
   * Provides two create() overloads:
   *   - create(key)          — parameterless, backward compatible
   *   - create(key, config)  — config-based, type-safe via std::any
   *
   * Usage:
   *   auto shape  = Shape::create("Circle");                   // default ctor
   *   auto shape2 = Shape::create("Circle", Circle::Config{5}); // with config
   *
   * @tparam Base The concrete base class of the plugin hierarchy
   */
  template< class Base >
  class PLUGIN_EXPORT Plugin
  {
    public:
      using key_type = typename PluginCatalog< Base >::key_type;

      Plugin( )                       = default;
      Plugin( Plugin< Base > const& ) = default;
      Plugin( Plugin< Base >&& )      = default;

      Plugin< Base >& operator=( Plugin< Base > const& ) = default;
      Plugin< Base >& operator=( Plugin< Base >&& )      = default;

      virtual ~Plugin( ) = default;

      /**
       * @brief Create a plugin instance using the default constructor.
       */
      static std::unique_ptr< Base > create( key_type const& key )
      {
        return catalog( ).create( key );
      }

      /**
       * @brief Create a plugin instance with a config object.
       *
       * The Config type is automatically wrapped in std::any.
       * It must match the type registered via REGISTER_WITH_CONFIG.
       *
       * @tparam Config  The concrete config struct (deduced)
       * @param  key     Registered plugin name
       * @param  config  Config object forwarded to the plugin constructor
       *
       * @throws std::runtime_error  if the plugin has no config factory
       * @throws std::bad_any_cast   if Config doesn't match registration
       */
      template< typename Config >
      static std::unique_ptr< Base > create( key_type const& key, Config const& config )
      {
        return catalog( ).create( key, std::any( config ) );
      }

      static void load( std::string const& sharedObjectName )
      {
        fedem::dso::DSOLoader::load( sharedObjectName );
      }

      static PluginCatalog< Base >& catalog( );
  };
}  // namespace plugin

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