Adr*_*och 6 c++ templates variadic-templates c++11
我正在尝试创建一种AddComponents()方法,可以一次创建多个组件并将其添加到实体中。我已经编写了一种一次添加一个组件的工作方法。
它具有以下签名:
template <class TComponent, typename... TArguments>
TComponent & AddComponent(TArguments&&... arguments);
Run Code Online (Sandbox Code Playgroud)
并按以下方式使用
entity.AddComponent<SomeComponent>(data1, data2, data3);
Run Code Online (Sandbox Code Playgroud)
我现在想创建一个函数,在一个函数中添加多个组件,即采用TComponents. 当然,数据也必须被传递,这就是事情变得丑陋的地方;我基本上需要一个参数包的参数包。然后该函数应该迭代TComponents(例如 using int i < sizeof...(Types))并调用AddComponent<T>(data...)每个TComponent。我经常使用模板,但我很难理解这个问题。
理想情况下,我希望它的使用方式如下:
entity.AddComponents<PositionComponent, SpriteComponent, TComponent>(
{ position },
{ texture, colour },
{ data1, data2 });
Run Code Online (Sandbox Code Playgroud)
在内部我需要一种方法来做类似的事情
for each TComponent : TComponents
{
this->AddComponent<TComponent>(forward...(data))
}
Run Code Online (Sandbox Code Playgroud)
从理论上讲,如果没有这个,我也许可以逃脱,但这似乎是一个有趣的问题。
如果人们可能质疑该函数的作用,这里是代码。
template <class TComponent, typename... TArguments>
inline TComponent & Entity::AddComponent(TArguments&&... arguments)
{
auto typeId = detail::GetComponentTypeID<TComponent>();
auto component = std::make_shared<TComponent>(eventManager, *this, std::forward<TArguments>(arguments)...);
componentList.push_back(component);
componentDictionary.insert(std::make_pair(typeId, component));
entityManager.AddEntityToGroup(*this, typeId);
this->AddPolymorphism(typeId, component);
eventManager.RaiseEvent(mbe::event::ComponentsChangedEvent(*this));
return *component;
}
Run Code Online (Sandbox Code Playgroud)
我会使用类似于 STL 最终所做的事情:将包的包作为元组包传递。
以成对的 emplace_back 为例:
stuct Widget {
int a;
std::string name = {};
};
std::pair<Widget, Widget>{
std::piecewise_construct,
std::forward_as_tuple(12, "values"),
std::forward_as_tuple(31)
};
Run Code Online (Sandbox Code Playgroud)
这里第一个参数告诉您需要分段构造,因此每个参数将充当一个“包”,它将扩展到该对的成员。在这种情况下,该对的元素的构造如下:
Widget first{12, "values"};
Widget second{31};
Run Code Online (Sandbox Code Playgroud)
就您而言,您似乎总是想构建N组件。所以解决方案是:
template<typename Component, typename Tuple>
void addComponentUnpack(Tuple&& tuple) {
std::apply([](auto&&... args) {
addComponent<Component>(std::forward<decltype(args)>(args)...);
}, std::forward<Tuple>(tuple));
}
template<typename... Components, typename... Tuples>
void addComponents(Tuples&&... tuples) {
(addComponentUnpack<Components, Tuples>(std::forward<Tuples>(tuples)), ...);
}
Run Code Online (Sandbox Code Playgroud)
因此,对于每个Component,您Tuple在包中都有一个对应的Components和Tuples。Component然后,每个元组都被发送到一个函数,该函数使用元组构造类型的单个组件Tuple。
此示例使用 C++17 功能(例如折叠表达式),std::apply但可以使用更多代码在 C++14 中实现。
但是,如果您不想使用元组作为参数,您始终可以直接接收类型的实例:
template<typename... Components>
void addComponents(Components&&... components) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
它的用法如下:
addComponents(
PositionComponent{12, 43},
CollisionComponent{},
SpriteComponent{"texture name"}
);
// or
addComponents<PositionComponent, CollisionComponent, SpriteComponent>(
{12, 42},
{},
{"texture name"}
);
Run Code Online (Sandbox Code Playgroud)
当然,这需要将组件从参数移动到实体中,这可能不是完全免费的,具体取决于情况。
| 归档时间: |
|
| 查看次数: |
1174 次 |
| 最近记录: |