Я создаю фабрику шаблонов для своего проекта, все работало нормально, пока мне не нужно было добавить дополнительный параметр в процесс создания объекта.
На фабрике есть два основных шаблона:
template <typename T>
class GenericFactory_c: boost::noncopyable
{
public:
typedef typename T::ObjectType_t ObjectType_t;
//basic creating with just 1 parameter (object name)
ObjectType_t Create(const String_c &className, const String_c &name) const
{
typename ObjectCreatorSet_t::const_iterator it = setObjectCreators.find(className, ObjectCreatorComp_s<T>());
if(it == setObjectCreators.end())
PH_RAISE(OBJECT_NOT_FOUND_EXCEPTION, "[EntityFactory_c::Create]", name);
return it->Create(name);
}
//"advanced" creation using an additional Y parameter
template <typename Y>
ObjectType_t Create(const String_c &className, const String_c &name, Y param) const
{
typename ObjectCreatorSet_t::const_iterator it = setObjectCreators.find(className, ObjectCreatorComp_s<T>());
if(it == setObjectCreators.end())
PH_RAISE(OBJECT_NOT_FOUND_EXCEPTION, "[EntityFactory_c::Create]", name);
return it->Create(name, param);
}
//rest of the code, probably irrelavent to the problem removed for clarity
};
Идея состоит в том, что для определенных типов будет использоваться только create с 2 параметрами, для других типов будет использоваться только create с 3 параметрами.
Это означает, что для определенного экземпляра Factory никогда не будетбудут использоваться обе версии, только одна.
Для возможности автоматической регистрации типов с использованием статических переменных я создал класс ObjectCreator, который определяется следующим образом:
template <typename T, typename Y>
class ObjectCreatorBase_c: public ObjectCreatorAutoUnlinkHook_t
{
public:
typedef T ObjectType_t;
typedef Y ObjectCreatorProc_t;
public:
ObjectCreatorBase_c(const String_c &name, ObjectCreatorProc_t proc):
strName(name),
pfnCreateProc(proc)
{
}
T Create(const String_c &name) const
{
return pfnCreateProc(name);
}
template <typename Z>
T Create(const String_c &name, Z param) const
{
return pfnCreateProc(name, param);
}
//"irrelevant" code removed
private:
String_c strName;
ObjectCreatorProc_t pfnCreateProc;
};
И дляТип EntityComponent, которому нужны два параметра для construtor (строка и ссылка на Entity). Я определяю создателя объекта следующим образом:
template <typename T, typename Y>
class ObjectCreator1_c: public ObjectCreatorBase_c<T, T(*)(const String_c &, Y )>
{
public:
ObjectCreator1_c(const String_c &name, ObjectCreatorProc_t proc):
ObjectCreatorBase_c(name, proc)
{
GenericFactory_c<ObjectCreator1_c >::GetInstance().Register(*this);
}
};
И создатель определяется так:
static ObjectCreator1_c<EntityComponentPtr_t, Entity_c &> CreatorForXYZ_CreatorObject_gl("XYZ", &XYZ::Create);
Фабрикадля этого определяется как:
typedef GenericFactory_c<ObjectCreator1_c<EntityComponentPtr_t, Entity_c &> > EntityComponentFactory_c;
И, наконец, для создания компонента я использую следующий код:
Entity_c::CreateCompXYZ()
{
EntityComponentFactory_c &factory = EntityComponentFactory_c::GetInstance();
EntityComponentPtr_t xyz = factory.Create("XYZ", "myXYZInstance", *this);
}
И, наконец, мойпроблема с кодом выше, компилятор, кажется, игнорирует ссылку на *this
и пытается создать копию объекта Entity, и я получаю неопределенную ссылку на Entity_c::Entity_c(const Entity_c &)
, это нормально, потому что Entity_c
не делаетесть конструктор копирования (не копируемый), но проблема в том, что этот код не пытается копировать Entity_c
, но использует ссылки.
Есть идеи?