Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ iterate over members of struct

Tags:

c++

Say I have a struct:

struct Boundary {
  int top;
  int left;
  int bottom;
  int right;
}

and a vector

std::vector<Boundary> boundaries;

What would be the most C++ style way to access the structs to get the sum of top, left, bottom and right separately?

I could write a loop like

for (auto boundary: boundaries) {
  sum_top+=boundary.top;
  sum_bottom+=boundary.bottom;
  ...
}

This seems like a lot of repetition. Of course I could do this instead:

std::vector<std::vector<int>> boundaries;

for (auto boundary: boundaries) {
  for(size_t i=0; i<boundary.size();i++) {
    sums.at(i)+=boundary.at(i)
  }
}

But then I'd loose all the meaningful struct member names. Is there a way so that I can write a something like the following function:

sum_top=make_sum(boundaries,"top");

Reflection does not seem to be an option in C++. I am open to use C++ up to Version 14.

like image 486
Amelse Etomer Avatar asked Dec 05 '19 13:12

Amelse Etomer


People also ask

Can you loop through a struct?

You can iterate through an array of structs but not the struct members. Learn about Classes. You have a struct with function as well as data members. You can add functions to structs too, but it's best to learn the whole shtick.

How do you access the structure members of a for loop?

Members in structs are designed to be accessed by name, as opposed to elements in arrays which are designed to be indexed. Computing addresses from offsets is a possibility but you still need to know the struct layout anyway — and on top, that layout can change with a compiler option or pragma.

How to iterate over a struct in C++?

Iterating over a struct in C++ 0 Adressing variables by variable names 2 How to traverse all fields of C++ class? 1 Having a iterable container where members are known at compile time -1 C++ iterate through struct by increasin pointer bit by bit 64 C++ preprocessor: avoid code repetition of member variable list 7

Is it possible to iterate through the members of a struct?

But you have a bigger problem - it's not guaranteed that you can iterate through the members of a struct type with a pointer like this. Even though all the members are the same type, it's not guaranteed that there won't be padding between members (it depends on the size of the bool type and the alignment requirements of your platform).

How to traverse all fields of C++ class?

How to traverse all fields of C++ class? 1 Having a iterable container where members are known at compile time -1 C++ iterate through struct by increasin pointer bit by bit 64 C++ preprocessor: avoid code repetition of member variable list 7

Is it possible to loop through all the members of a struct?

The answer to the question is not 'no'. You can easily iterate through the members of a struct and print them using standard C++: A a; printf(a.a); printf(a.b); printf(a.c);. There are plenty of ways to make the syntax more like the desired 'loop', using some kind of custom reflection mechanism.


1 Answers

std::accumulate(boundaries.begin(), boundaries.end(), 0, 
 [](Boundary const & a, Boundary const & b) { return a.top + b.top); });

(IIRC the Boundary const &'s can be auto'd in C++17)

This doesn't make it generic for the particular element, which - indeed, due to the lack of reflection - isn't easy to generalize.

There are a few ways to ease your pain, though;

You could use a pointer-to-member, which is fine for your szenario but not very c-plusplus-y:

int Sum(vector<Boundary>const & v, int Boundary::*pMember)
{
   return std::accumulate( /*...*/, 
     [&](Boundary const & a, Boundary const & b)
     {
        return a.*pMember + b.*pMember;
     });
}

int topSum = Sum(boundaries, &Boundary::top);

(For pointer-to-member, see e.g. here: Pointer to class data member "::*")

You could also make this generic (any container, any member type), and you could also replace the pointer-to-member with a lambda (also allowing member functions)

like image 179
peterchen Avatar answered Nov 15 '22 22:11

peterchen