Здравствуйте, remark, Вы писали:
R>http://gzip.rsdn.ru/forum/message/1788774.1.aspxАвтор: remark
Дата: 17.03.06
IMHO, сложное очень решение

Вот смотри, один класс и в нём простой nested class template:
template< typename TInterface, typename TPtr = shared_ptr<TInterface> > class ObjectsFactory {
public:
typedef std::string TypeId;
typedef TPtr Ptr;
static Ptr Create( const TypeId& id )
{
CreateFunction foo* = db()[id];
assert( foo != 0 );
return foo();
}
template<typename T> class Registrar {
public:
Registrar( const TypeId& id ) : id( id ) { reg( id, &creator ); }
~Registrar() { unreg( id ); }
private:
const TypeId id;
Registrar( const Registrar& );
void operator = ( const Registrar& );
static Ptr creator() { return new T; }
};
private:
typedef Ptr CreateFunction();
typedef std::map<TypeId, CreateFunction*> DB;
static DB& db()
{
static DB creators; // синглетон Маерса, так как Registrar -- статические объекты.
return creators;
}
static void reg( const TypeId& id, CreateFunction* foo )
{
assert( foo != 0 && db()[id] == 0 );
db()[id] = foo;
}
static void unreg( const TypeId& id )
{
assert( db()[id] != 0 );
db()[id] = 0;
}
};
Ну и теперь использование:
// MyInterface.h
struct IMyInterface { virtual ~IMyInterface() {} };
typedef ObjectsFactory<IMyInterface> MyFactory;
const char* const MyInterfaceImpl1TypeId = "MySubsystem::MySubsubsystem::MyInterfaceImpl1";
const char* const MyInterfaceImpl2TypeId = "MySubsystem::MySubsubsystem::MyInterfaceImpl2";
// MyInterfaceImpl1.h
class MyInterfaceImpl1 : public IMyImterface {
public:
// тут реализация
};
// В MyInterfaceImpl1.cpp
static MyFactory::Registrar<MyInterfaceImpl1> impl( MyInterfaceImpl1TypeId );
// MyInterfaceImpl2.h
class MyInterfaceImpl2 : public IMyImterface {
public:
// тут реализация
};
// В MyInterfaceImpl2.cpp
static MyFactory::Registrar<MyInterfaceImpl2> impl( MyInterfaceImpl2TypeId );
IMHO радикально проще и прямее

И пользователям MyInterface, кстати, не надо знать о MyInterfaceImpl1.h, MyInterfaceImpl2.h и т. д...
Если таки хочется обязать пользователя иметь в классе-реализации статическое поле с TypeId, то можно приделать в ObjectFactory::Registrar() занчение параметра по умолчанию T::TypeId, например.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском