模板工厂给出链接器错误并忽略引用类型

发布于 2024-11-16 11:02:06 字数 3648 浏览 3 评论 0原文

我正在为我的项目创建一个模板工厂,一切正常,直到我需要向对象创建过程添加额外的参数。

该工厂有两个主要模板:

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
};

其想法是,对于某些类型,仅使用具有 2 个参数的创建,对于其他类型,仅使用具有 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 类型,我定义了一个对象创建器,如下所示

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);
}

最后是我的问题,使用上面的代码,编译器似乎忽略了对 的引用*这个并尝试创建 Entity 对象的副本,然后我得到对 Entity_c::Entity_c(const Entity_c &) 的未定义引用,没关系,因为 Entity_c 没有副本构造函数(不可复制),但问题是因为此代码预计不会尝试复制 Entity_c ,而是使用它的引用。

有什么想法吗?

I am creating a template factory for my project, everything was working fine until I need to add an extra parameter to the object creation process.

The factory has two main templates:

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
};

The idea is that for certain types, only the create with 2 parameters will be used, for other types only the create with 3 parameters will be used.

That means that for a certain Factory instantiation, never both versions will be used, just one.

For being able to auto register types using static variables, I created a ObjectCreator class, this is defined as follows:

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;
};

And for a EntityComponent type that needs two parameters on construtor (string and Entity reference) I define an object creator as below:

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);
        }
};

And a creator is defined liked this:

static ObjectCreator1_c<EntityComponentPtr_t, Entity_c &> CreatorForXYZ_CreatorObject_gl("XYZ", &XYZ::Create);

A factory for this is defined like:

typedef GenericFactory_c<ObjectCreator1_c<EntityComponentPtr_t, Entity_c &> > EntityComponentFactory_c;

And finally, for creating a component I use the code below:

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

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

And finally comes my problem, with the code above, the compiler appears to ignore the reference to the *this and tries to create a copy of the Entity object and I get a undefined reference to Entity_c::Entity_c(const Entity_c &), that is ok, because Entity_c does not have a copy constructor (non copyable), but the problem is because this code is not expected to try to copy Entity_c, but uses it references.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

皇甫轩 2024-11-23 11:02:06

如果此函数

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)代码>此处)。

当然,如果它是不可复制的,这不起作用!

If this function

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

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

is actually calling this template for a 3 parameter 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

it really is trying to copy Entity_c (it being Y here).

Of course this doesn't work if it is non-copyable!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文