With C++26 reflection, we can simply iterate all data members of an object:
#include <iostream>
#include <meta>
struct Foo {
int x;
int y;
};
void PrintFoo(const Foo& foo) {
constexpr auto members =
define_static_array(nonstatic_data_members_of(^^Foo, std::meta::access_context::current()));
template for (constexpr auto member : members) {
std::cout << identifier_of(member) << ": " << foo.[:member:] << std::endl;
}
}
int main() {
PrintFoo(Foo { .x = 888, .y = 999 });
return 0;
}
where I can iterate data members with template for.
However, if I want to iterate with STL algorithms such as for_each, transform, ... and even ranges (std::views::xxx) to simplify the codes if the logic gets more complicated, I will get compilation errors, since the STL algorithms uses for instead of template for, and I cannot make the parameter member of the lambda expression be constexpr:
void PrintFoo(const Foo& foo) {
constexpr auto members =
define_static_array(nonstatic_data_members_of(^^Foo, std::meta::access_context::current()));
std::ranges::for_each(members, [&foo](auto member) {
std::cout << identifier_of(member) << ": " << foo.[:member:] << std::endl;
}));
}
<source>:15:59: error: splice operand must be a constant expression
15 | std::cout << identifier_of(member) << ": " << foo.[:member:] << std::endl;
...
<source>:14:27: error: expressions of consteval-only type are only allowed in constant-evaluated contexts
14 | std::ranges::for_each(members, [&foo](auto member) {
| ^~~~~~~
https://gcc.godbolt.org/z/MMsd38Wz7
However, most algorithms are constexpr which means they may be used in const-evaluated contexts. Is there anyway to use STL algorithms here to simplify my code?
[:and:]must be a constant expression, and function parameter names are not constant expressions. It would be possible if you can avoid[:member:]though.template for" a simpler and more intuitive form?std::ranges::for_each(members, [](std::meta::info member) { (void)identifier_of(member); });: gcc.godbolt.org/z/aveE9c31d