Home > Mobile >  iterate through all struct member
iterate through all struct member

Time:03-05

I am looking for a way to iterate through all of PATTERNS's members. I cannot use vector. Ideally, I want to be able to get the next member of the struct and reset it when the end is reached. What I understand is that I essentially want a linked list. Thing is that I have many struct such as this one and I find it inefficient for me to create a struct containing one array with a pointer to the next struct containing the next array.

Q: How would you iterate through all of the struct's members?

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

Edit: to answer @user17732522 - I'm trying to replicate code from python (itertools). It's mainly for convenience of use and somewhat more OOP. The quick fix is just to make a 2D bool array.

CodePudding user response:

The short answer is "You can't.".

C doesn't offer any reflection features because they limit the development of the language without breaking backwards compatibility.

You can use std::vector and a little type erasure (like std::variant) to achieve what you want.

If you really want reflection you can use Boost Reflect Library or look into what extensions your compiler supports. I wouldn't recommend either of those options though.

CodePudding user response:

There's no way to iterate members in C (without meta programming).

You could make a small change to use an array as a member. You can iterate arrays in C :

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

Referring to the subarrays with names is still possible, but it requires considerable boilerplate:

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

I couldn't figure out if this can work with default member initialiser such as the one in your example.

CodePudding user response:

What you're looking for is called "static reflection". C doesn't support it yet.
In the meantime you can use a code generator to look at your code and produce functions to iterate through elements of the struct.
That can be done using Google's Protocol Buffers (protobuf), although you'll have to write your structs in protobuf and then use the generated C code.
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 feature you were looking for in C . PyBind11 can be useful for setting-up test environments.
I think PyBind11 scans your C code. The process is not entirely automatic, but what can you do?

CodePudding user response:

Well a quick and dirty way is to simply cast your structure to an array of bool and print that:

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

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

You can see it in action here.

Just take care that there's no compiler alignment being performed or you'll run into trouble. Use #pragma pack or your specific compiler's flavor to disable it.

  •  Tags:  
  • c
  • Related