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.
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.
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.
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
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? 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
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.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With