繁体   English   中英

遍历所有结构成员

[英]iterate through all struct member

我正在寻找一种遍历所有PATTERNS成员的方法。 我不能使用vector 理想情况下,我希望能够获取struct的下一个成员并在到达末尾时将其重置。 我的理解是我本质上想要一个链表。 事情是我有很多struct ,比如这个结构,我发现创建一个包含一个数组的struct并指向包含下一个数组的下一个struct的指针对我来说效率很低。

问:您将如何遍历struct的所有成员?

struct PATTERNS {
  bool P0[3] = {0, 0, 1};
  bool P1[3] = {0, 1, 1};
  bool P2[3] = {1, 1, 1};
};

编辑:回答@user17732522 - 我正在尝试从 python (itertools) 复制代码。 主要是为了方便使用,有点多 OOP 快速修复只是制作一个二维布尔数组。

简短的回答是“你不能”。

C++ 不提供任何反射功能,因为它们在保持向后兼容性时限制了语言。

您可以使用std::vector和一些类型擦除(如std::variant )来实现您想要的。

如果你真的想要反射,你可以使用Boost Reflect Library或者查看你的编译器支持的扩展。 不过,我不会推荐这些选项中的任何一个。

没有办法迭代 C++ 中的成员(没有元编程)。

您可以做一个小的更改以使用数组作为成员。 可以在C++中迭代arrays:

struct PATTERNS {
    bool P[3][3] = {
        {0, 0, 1},
        {0, 1, 1},
        {1, 1, 1},
    };
};

使用名称引用子数组仍然是可能的,但它需要相当多的样板:

union PATTERNS {
    using PA = bool[3];
    struct {
        PA P[3];
        operator       PA&() &        { return  P[0]; }
        operator const PA&() const &  { return  P[0]; }
        PA* operator&()               { return &P[0]; }
    } P0;
    
    struct {
        PA P[3];
        operator       PA&() &        { return  P[1]; }
        operator const PA&() const &  { return  P[1]; }
        PA* operator&()               { return &P[1]; }
    } P1;

    struct {
        PA P[3];
        operator       PA&() &        { return  P[2]; }
        operator const PA&() const &  { return  P[2]; }
        PA* operator&()               { return &P[2]; }
    } P2;

    struct {
        PA P[3];
        PA* begin() { return std::begin(P); }
        PA* end()   { return std::end(P);   }
    } P;
};

我无法弄清楚这是否可以与默认成员初始化器一起使用,例如您示例中的初始化器。

您正在寻找的是所谓的“静态反射”。 C++暂不支持。

同时,您可以使用代码生成器来查看您的代码并生成函数来遍历结构的元素。

这可以使用 Google 的 Protocol Buffers (protobuf) 来完成,尽管您必须在 protobuf 中编写结构,然后使用生成的 C++ 代码。

I've seen people use a different code generator: PyBind11 which interfaces between C++11 and Python. It produces object declarations for C++ and Python to use, and then without changing any of the C++ code, you can use dynamic reflection in Python to gain the您在 C++ 中寻找的功能。PyBind11 可用于设置测试环境。

我认为 PyBind11 会扫描您的 C++ 代码。 这个过程不是完全自动的,但你能做什么?

我建议你制作一个 arrays 的数组(通常称为二维数组)。 然后,您可以向 class 添加一个迭代器,以简化对所有元素的迭代。

例子:

#include <iostream>

struct PATTERNS {
    bool P[3][3] = {
        {0, 0, 1},
        {0, 1, 1},
        {1, 1, 1},
    };

    // references to sub-arrays if you need them:
    bool (&P0)[3] = P[0];
    bool (&P1)[3] = P[1];
    bool (&P2)[3] = P[2];

    // basic iterator support (not at all a complete iterator implementation)
    struct iterator {

        // non-const dereferencing
        bool& operator*() { return p[i / 3][i % 3]; };

        iterator& operator++() {
            ++i;
            return *this;
        }

        bool operator==(const iterator& rhs) const { return i == rhs.i; }
        bool operator!=(const iterator& rhs) const { return !(*this == rhs); } 

        size_t i;          // current index
        bool (&p)[3][3];   // a reference to the actual bool[3][3]
    };

    // iterate over all the 3x3 bools:
    iterator begin() { return {0, P}; }
    iterator end() { return {9, P}; }

    // iterate over a specific row of bools:
    iterator begin(size_t row) { return {row * 3, P}; }
    iterator end(size_t row) { return {(row + 1) * 3, P}; }
};

使用示例:

int main() {
    PATTERNS pat;
    // all
    for (bool v : pat) {
        std::cout << v << ' ';
    }
    std::cout << '\n';

    // a certain row
    size_t row = 1;
    for (auto it = pat.begin(row); it != pat.end(row); ++it) {
        std::cout << *it << ' ';
    }
    std::cout << '\n';
}

好吧,一种快速而肮脏的方法是简单地将您的结构转换为bool数组并打印:

PATTERNS ptn;
auto p = (bool *)&ptn;

copy(p, p + 9, ostream_iterator<bool>(cout, " "));

您可以在此处查看实际效果。

请注意不要执行编译器 alignment,否则您会遇到麻烦。 使用#pragma pack或您的特定编译器风格来禁用它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM