Я использую синглтон с членом для регистрации, в основном:
template< typename KeyType, typename ProductCreatorType >
class Factory
{
typedef boost::unordered_map< KeyType, ProductCreatorType > CreatorMap;
...
};
Используя Loki, я получаю что-то вроде этого:
typedef Loki::SingletonHolder< Factory< StringHash, boost::function< boost::shared_ptr< SomeBase >( const SomeSource& ) > >, Loki::CreateStatic > SomeFactory;
Регистрация обычно выполняется с помощью макросатакие как:
#define REGISTER_SOME_FACTORY( type ) static bool BOOST_PP_CAT( type, __regged ) = SomeFactory::Instance().RegisterCreator( BOOST_PP_STRINGIZE( type ), boost::bind( &boost::make_shared< type >, _1 ) );
Эта установка имеет ряд преимуществ:
- Работает, например, с boost :: shared_ptr <>.
- Не требует обслуживанияОгромный файл для всех регистрационных нужд.
- Очень гибок в работе с создателем, все идет очень хорошо.
- Макрос охватывает наиболее распространенный вариант использования, оставляя дверь открытой для альтернатив.
Тогда достаточно вызвать макрос в файле .cpp, чтобы зарегистрировать тип при запуске во время статической инициализации.Это прекрасно работает, если регистрация типа является частью статической библиотеки, и в этом случае она не будет включена в ваш двоичный файл.Единственные решения, которые собирают регистрацию как часть библиотеки, которую я видел, - это иметь один огромный файл, который выполняет регистрацию явно как часть некоторой процедуры инициализации.Вместо этого я сейчас делаю, чтобы у меня была папка клиента с моей библиотекой, которую пользователь включает в состав двоичной сборки.
Из вашего списка требований я считаю, что это удовлетворит все, кроме использования класса регистратора.