在C++中解决缺少模板化虚函数的问题

Sam*_*erg 5 c++ templates c++11

我不确定如何最好地表达这个问题,但我不是问如何实现模板化的虚函数本身.我正在构建一个实体组件系统,我有两个重要的类 - WorldEntity.World实际上是一个抽象类,实现(让我们称之为WorldImpl)是一个模板化的类,允许使用自定义分配器(可以与之一起使用std::allocator_traits).

组件是我们可以附加到实体的任何数据类型.这是通过调用assign在实体上命名的模板化函数来完成的.

这就是问题所在:我在创建和初始化组件时试图让实体使用世界的分配器.在一个完美的世界中,你会调用Entity::assign<ComponentType>( ... )哪个会要求WorldImpl用任何适当的分配器来创建组件.但是这里存在一个问题 - 实体有一个指向World虚拟函数的指针,我不知道虚函数.

以下是一个可能使问题更加明显的插图:

class Entity
{
  template<typename ComponentType>
  void assign(/* ... */)
  {
    /* ... */
    ComponentType* component = world->createComponent<ComponentType>(/* ... */);
    /* ... */
  }

  World* world;
};

// This is the world interface.
class World
{
  // This is the ideal, which isn't possible as it would require templated virtual functions.
  template<typename ComponentType>
  virtual ComponentType* createComponent(/* ... */) = 0;
};

template<typename Allocator>
class WorldImpl : public World
{
  template<typename ComponentType> // again, not actually possible
  virtual ComponentType* createComponent(/* ... */)
  {
    // do something with Allocator and ComponentType here
  }
};
Run Code Online (Sandbox Code Playgroud)

看上面的代码实际上是不可能的,这是真正的问题:对于像这样的类层次结构,为了使用ComponentType和Allocator模板参数调用某些函数,我还需要做些什么黑魔法?这是最终目标 - 一个函数调用某个对象,并且可以使用两个模板参数.

Rum*_*rak 2

我想说实体属于某种世界,并使用世界参数将它们作为模板。然后你可以忘记所有的继承,virtual只实现满足所需接口的世界,例如

template<typename World>
class Entity
{
  template<typename ComponentType>
  void assign(/* ... */)
  {
    /* ... */
    ComponentType* component = world.createComponent<ComponentType>(/* ... */);
    /* ... */
  }

  World world;
};

template<typename Allocator>
class WorldI
{
  template<typename ComponentType>
  ComponentType* createComponent(/* ... */)
  {
    // do something with Allocator and ComponentType here
  }
};
Run Code Online (Sandbox Code Playgroud)