// 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( )