gpt4 book ai didi

c++ - 如何使用和访问参数包的模板参数包

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:26:21 24 4
gpt4 key购买 nike

简短介绍

我正在尝试创建一个 AddComponents()一次创建多个组件并将其添加到实体的方法。我已经编写了一种一次添加一个组件的工作方法。

它具有以下签名:

template <class TComponent, typename... TArguments>
TComponent & AddComponent(TArguments&&... arguments);

并按以下方式使用

entity.AddComponent<SomeComponent>(data1, data2, data3);

我现在想创建一个将多个组件添加到一个函数中的函数,即采用 TComponents 的参数包.当然,数据也必须传递,这就是事情变得糟糕的地方;我基本上需要一个参数包的参数包。然后函数应该遍历 TComponents (例如使用 int i < sizeof...(Types) )并调用 AddComponent<T>(data...)对于每个 TComponent .我已经使用了很多模板,但我很难理解这个问题。

我想要什么

理想情况下,我希望它像这样使用:

entity.AddComponents<PositionComponent, SpriteComponent, TComponent>(
{ position },
{ texture, colour },
{ data1, data2 });

在内部我需要一种方法来做类似的事情

for each TComponent : TComponents
{
this->AddComponent<TComponent>(forward...(data))
}

理论上,没有这个我也许可以逃脱,但这似乎是一个有趣的问题。

添加组件代码

为了防止人们质疑函数的作用,这里是代码。

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

最佳答案

我会使用类似于 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)
};

这里的第一个参数告诉你想要分段构造,所以每个参数都将充当一个“包”,将扩展到对的成员中。在这种情况下,对的元素构造如下:

Widget first{12, "values"};
Widget second{31};

在您的情况下,您似乎总是想要构造 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)), ...);
}

因此,对于每个 Component,您在 ComponentsTuple 包中都有一个相应的 Tuple。然后,每个元组被发送到一个函数,该函数使用元组 Tuple 构建类型为 Component 的单个组件。

此示例使用 C++17 功能,例如 fold expressionsstd::apply 但它可以在 C++14 中使用更多代码来实现。


但是如果您不想使用元组作为参数,您总是可以直接接收您的类型的实例:

template<typename... Components>
void addComponents(Components&&... components) {
// ...
}

它的用法是这样的:

addComponents(
PositionComponent{12, 43},
CollisionComponent{},
SpriteComponent{"texture name"}
);

// or

addComponents<PositionComponent, CollisionComponent, SpriteComponent>(
{12, 42},
{},
{"texture name"}
);

当然,这需要将组件从参数移动到实体中,这可能不是完全免费的,具体取决于具体情况。

关于c++ - 如何使用和访问参数包的模板参数包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55482994/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com