I am reading P2996 (https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2996r2.html) paper which introduces reflection in c++ language. There are some examples showing how to use those features. In example 3.2 we have following code:
consteval auto member_number(int n) {
return std::meta::nonstatic_data_members_of(^S)[n];
}
But in example 3.14 there is:
std::vector args = {^To, ^From};
for (auto mem : nonstatic_data_members_of(^From)) {
args.push_back(reflect_value(mem));
}
My question is why do we need to use reflect_value
in the second example? When we have to use that function in general case and how we could know that product of nonstatic_data_members_of
on not enough?
In the second example,
mem
is a std::meta::info
that reflects a non-static data member of From
.reflect_value(mem)
is a std::meta::info
that reflects the value of mem
. (That is, [:reflect_value(mem):] == mem
.)Remember that substitute
operates on the reflected entities (e.g. substitute(^std::tuple, {^int})
is ^std::tuple<int>
, not ^std::tuple<^int>
which is invalid anyway). In the example, get_struct_to_tuple_helper
wants to substitute into
template <typename To, typename From, std::meta::info ... members>
constexpr auto struct_to_tuple_helper(From const& from) -> To
So the arguments to substitute
(after ^To
and ^From
) must reflect std::meta::info
values (not just be such values), which necessitates the use of reflect_value
.
(By the way, it seems that reflect_value
got renamed to reflect_result
in P2996R3, but the main functionality is unchanged.)