C ++如何将参数绑定到具有相同返回类型的函数,并将它们全部存储在一个容器中

时间:2018-05-21 12:18:43

标签: c++ components

意图和背景

我有一个名为Component的班级。 看起来有点像(PSEUDO CODE):

template <class t>
class Component{
private:
    map<Entity, List<t>> attachedEntities;
public:
//Some other stuff like constructors, setters and getters etc.
     template<typename... Args>
     void addTo(const Entity &en, Args...args)
    {
        this->addTo(en,std::make_shared<t>(std::forward<Args>(args)...));
    }

    template < typename U, typename std::enable_if< std::is_base_of<t, U>::value, U>::type* = nullptr >
    void addTo( const Entity &en,U* ptr)
    {
        this->addTo(en,shared_ptr<t>(ptr));
    }
    void addTo(const Entity &en,const std::shared_ptr<t> ptr)
    {
        /*
            Does the actual adding to the map
        */
    }
}

(对于任何想知道实体与此问题的上一版本中的目标相同的人。实体在第二个想法上更有意义)

出于教育目的,我不愿意为传递的变量编写包装器。

如您所见,类Component有3个addTo函数。现在我的系统是一个简单的组件实体系统,其中实体表示一个UUID,用作地图中的键。当这些地图与单个UUID一起进入上下文时,可以“形成”一个完整的实体。

例如,实体可能在

中有一个条目
  • StringComponent
  • TextureComponent
  • ModelComponent

当一个函数遍历所有模型并查找拟合字符串和纹理时,它将呈现我们想要的东西。例如,与模型组件中的实体关联的模型可以是胸部模型,纹理是胸部模型的漫反射纹理,字符串可以简单地说出玩家在与之交互之前应该看到的内容。

这在我的程序中已经很好用!然而,我正在努力的是为对象制作某种模板,然后一遍又一遍地实例化。对于此示例,我可以说我想创建一个代表Bullet

的实体

子弹可能有:

  • 表示其外观的模型
  • 用于检测物品何时与其发生碰撞的CollissionBox
  • 影响时播放的声音
  • 某种Tag(StringComponent),以确保更新功能正确更新它(所以它可能会有标签“Bullet_big”)

这再次起作用,但是现在只是让Enitity免于被删除,只是让其他子弹成为该实体的副本。这很糟糕,原因如下:

  • 它为游戏添加了一些可以与之交互但不会被删除的内容。如果我这样做,那么除了删除之外的所有东西都是不可能的,这仍然会增加开销,因为当调用get或set时必须给出一些替换
  • 它在每张地图中都是一个不可用的项目。对于较大的程序而言,这可能会成为一个问题,其中可能有数百个“模板”浮动
  • 如果模板被删除,无论是通过监督开发人员还是通过错误,副本很可能会导致崩溃或开始行动。

我实际上正在努力

我现在要做的是写一个Blueprint课程

这门课应该只是:

  • 可用于创建所有具有相同组件的新实体的容器。
  • 未在任何地图中实际参与。
  • Aaaand无需手动检查每个组件名称以确定要添加的名称(这将是愚蠢的)。

以下是我的想法:

class Blueprint{
private:
    vector<function<???>> frozenAddFunctions; //Some way of storing all the functions with the init paramters but WITHOUT the entity specified;
public:
    template<t,typename... Args>
    void addTo(Component<t>, Args...args){
    //Somehow binding the approperate addTo overload to the arguments
    }
    void applyOnto(Entity &en){
        for(function f:this->frozenAddFunctions){
            f(en); //somehow invoke the addTo functions onto the Entity.
        }
    }

如果这是不可能的,请帮助我找到实现这一目标的方法,同时避免我列出的负面因素。

提前致谢。

我希望这种表现更好。

1 个答案:

答案 0 :(得分:1)

似乎你想要:

class Blueprint
{
private:
    std::vector<std::function<void(Entity &)>> functions;
public:
    template<typename T, typename... Args>
    void addTo(Component<T>& component, Args...args)
    {
        functions.emplace_back([=, &component](Entity& ent)
        {
            component.AddTo(ent, args...);
        });
    }

    void applyOnto(Entity &en)
    {
        for(const auto& f : functions){
            f(en);
        }
    }
};