Is there a way to loop over different data members of an object in C++

(C++20) Looping over a known number of public members: structured bindings in a range-based for loop initialization statement

As of C++20 we may combine structured bindings with range-based for loop initialization statements (the latter is a C++20 feature):

Grammar

for ( init-statement(optional) range-declaration : range-expression ) ...

Specifically, using structured bindings as the init-statement in a range-based for loop:

#include <iostream>

class Foo {
public:
    double x, y, z;

    Foo(double x, double y, double z) : x(x), y(y), z(z) {}
};

int main() {
    const Foo foo(1., 2., 3.);

    for (auto [x, y, z] = foo; auto e : {x, y, z}) {
        std::cout << e << " ";
    } // 1 2 3

    return 0;
}

Note, however, that you can only use structured bindings to decompose public members of your class (in your example all members are public). Moreover, for the initializer list in the range-expression of the range based for loop, you may not have conflicting types, meaning this approach is limited to the context of your example: where all public members are of the same type.

Why use the structured bindings instead of just list-initializing the class members directly?

Now, if the (public) members of your class as well as the instance of it all have very brief names, we may want to consider omitting the structured bindings and instead list-initialize the class members directly:

const Foo f(1., 2., 3.);
for (auto e : {f.x, f.y, f.z}) {
    std::cout << e << " ";
} // 1 2 3

However, albeit arguably briefer, the drawback is that we no longer get any help from the compiler in spotting whether we've actually exactly decomposed all public members (no less, no more) or not, a check that is present when we use structured bindings:

for (auto [x, y] = foo; auto e : {x, y}) { /* ... */ }
// error: type 'Foo' decomposes into 3 elements, 
//        but only 2 names were provided

for (auto [x, y, z, xx] = foo; auto e : {x, y, z, xx}) { /* ... */ }
// error: type 'Foo' decomposes into 3 elements, 
//        but 4 names were provided

Tags:

C++