Фабрика шаблонов дает ошибку компоновщика и игнорирует тип ссылки - PullRequest
1 голос
/ 17 июня 2011

Я создаю фабрику шаблонов для своего проекта, все работало нормально, пока мне не нужно было добавить дополнительный параметр в процесс создания объекта.

На фабрике есть два основных шаблона:

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, но использует ссылки.

Есть идеи?

1 Ответ

1 голос
/ 04 июля 2011

Если эта функция

Entity_c::CreateCompXYZ()
{
    EntityComponentFactory_c &factory = EntityComponentFactory_c::GetInstance();

    EntityComponentPtr_t xyz = factory.Create("XYZ", "myXYZInstance", *this);
}

фактически вызывает этот шаблон для 3-х параметров Create

//"advanced" creation using an additional Y parameter
template <typename Y>
ObjectType_t Create(const String_c &className, const String_c &name, Y param) const

, то на самом деле это , пытаясь скопировать Entity_c (здесь Y).

Конечно, это не сработает, если его нельзя скопировать!

...