返回类型取决于静态参数包字段
Return type which depends on static parameter pack fields
我最近一直在试验参数包,因为它们似乎满足了我开发中相当大的需求。但是,我一直遇到一个问题,参数包似乎是一个可行的解决方案,但我无法弄清楚这个特定问题。手头的问题是如何获取参数包中的每个类型,从该类型的静态字段中检索第 n 个元素,并在元组中返回该元素(以及其他元素)。如果措辞有点不清楚,我目前的用例如下:
/* 警告:可能是无端的细节 */
我的程序的体系结构是实体组件系统的体系结构。本质上,有多个系统定义了程序不同区域的逻辑。这些系统作用于由多个组件(包含特定数据片段,例如DescriptionComponent)组成的实体。每个系统将验证给定实体是否具有所有必需的组件,然后执行特定于系统的逻辑。
为此,我创建了一个组件基类,从中派生特定组件。每个派生组件都包含一个静态向量,该向量充当该类型所有组件的管理器。每个组件都有一个 entityId 字段,该字段引用其所属实体,静态向量在此 id 上排序。
目前,在给定的系统中,我能够通过查看系统所需的组件来找到适用的实体,然后找到都包含相同 entityId 的组件集并对这些组件执行逻辑。但是,此时我正在执行手动迭代组件的静态向量的逻辑,因为每个系统在组件类型方面都有不同的要求。
一个简单的例子,以防万一上面不清楚:
假设显示系统需要一个PictureComponent和一个PositionComponent。现在假设管理这些类型的静态字段如下:
PictureComponent::elements = [(picture: "somePic.jpg", id: 1), (picture: "otherPic.jpg", id: 2)]
PositionComponent::elements = [(pos: (1,2), id: 2), (pos: (4,5), id: 3)]
目前,每个组件都有自己的迭代器。从零开始,我们使用最低的 entityId 提高组件索引(因为向量是按此键排序的)。在上面的例子中,我们会尝试索引 (0,0),看到 id 1 小于 id 2,所以增加第一个索引。然后我们尝试 (1,0),看到两个组件都有 entityId 2,并将它们作为一对传递给系统以执行逻辑。然后,我们将两个索引都碰到,尝试 (2,1),并超出 PictureComponent 向量的界限,然后完成。
/* 结束 无端细节 */
我为这个问题设想的解决方案是单个模板化参数包类,该类接受所需的组件类型并输出其 entityId 都匹配的组件元组。其伪代码如下
template <typename... RequiredComponentTypes>
class ComponentIterator {
/* standard input iterator functionality*/
...
array componentIndices // same size as our param pack, one index per type
tuple<RequiredComponentTypes...> getNextSetOfComponents() {
while every component's entity id is not equal:
find the currently indexed component with the lowest entity id;
increment the current index of that component type;
out of the while, once we have a set of components with the same entity id:
return a tuple of the indexed components for each type. **//this is the part I have no idea how to do**
}
}
如代码中所述,将元组的值从索引检索到类型的静态字段的过程是我不确定的部分。对于任意数量的模板参数,手动执行都很简单(如果我有一组命名参数化类型,那么制作元组就像使用适当的值调用make_tuple一样简单。但是,在处理参数包时,我不确定如何解决这个问题。
你们可以提供的任何帮助将不胜感激,如果您需要任何澄清或更多详细信息,请随时告诉我。谢谢!
你可以做这样的事情:
template <typename... Ts>
class ComponentIterator {
static constexpr std::size_t size = sizeof...(Ts);
public:
ComponentIterator() : indices(), finished(false) { adjust(); }
std::tuple<Ts&...> get()
{
return get(std::index_sequence_for<Ts...>());
}
ComponentIterator& operator ++()
{
for (auto& e : indices) {
++e;
}
adjust();
return *this;
}
bool is_finished() const { return finished; }
private:
void adjust()
{
adjust(std::index_sequence_for<Ts...>());
}
template <std::size_t...Is>
std::tuple<Ts&...> get(std::index_sequence<Is...>)
{
return std::tie(Ts::elements[indices[Is]]...);
}
template <std::size_t...Is>
void adjust(std::index_sequence<Is...>) {
bool is_ended[size] = {indices[Is] == Ts::elements.size()...};
if (std::any_of(std::begin(is_ended), std::end(is_ended),
[](bool b) { return b; })) {
finished = true;
return;
}
int min_value = std::min({Ts::elements[indices[Is]].id...}) - 1;
for (;;)
{
++min_value;
bool increases[size] = {increase_until<Ts>(indices[Is], min_value)...};
if (std::any_of(std::begin(increases), std::end(increases),
[](bool b) { return !b; })) {
finished = true;
return;
}
const int ids[size] = {Ts::elements[indices[Is]].id...};
if (std::all_of(std::begin(ids), std::end(ids),
[min_value](int id) { return id == min_value;})) {
return;
}
}
}
template <typename T>
bool increase_until(std::size_t& index, int min_value)
{
for (; index != T::elements.size(); ++index) {
if (min_value <= T::elements[index].id) {
return true;
}
}
return false;
}
private:
std::array<std::size_t, size> indices;
bool finished;
};
现场示例
- 将结构字段的类型展开为可变模板参数
- 将位字段导出到数组
- 为了方便起见,我应该避免公开私有字段变量吗
- 当字段可以为null时,如何使用C++接口在Avro中写入数据
- 在java中读取c++字节的位字段
- 链接器找不到在虚拟类 c++ 中访问的静态字段的符号
- 私有字段对象与私有继承?
- 声明没有默认构造函数的字段
- C++内存模型和位字段的最大序列
- 声明为无效的变量或字段'...' Ardunio 编译器上的错误
- 如何在QByteArray中放置和检索位字段而不会感到痛苦?
- C++ win32 如何使密码字段可选并启用复制和粘贴?
- 如何通过UDP接收QByteArray并将其解析为位字段结构?
- 仅匹配集合中的某些字段
- 存储在哪个内存段(代码/数据段)类(员工)中?
- TOS字段从Linux的TCP插座上接收到的数据包获取
- 返回类型取决于静态参数包字段
- 原始数据包创建导致 IP 字段顺序不正确
- 套接字将在一段时间后死亡而不能重新连接
- c++ Unix域套接字工具包