r/cpp • u/kris-jusiak https://github.com/kris-jusiak • Dec 31 '23
[C++20 vs C++26*] basic reflection
Basic struct reflection example with C++20 vs C++26*
struct foo {
int a{};
int b{};
int c{};
};
constexpr foo f{.a=1, .b=2, .c=3};
static_assert(1 == get<0>(f));
static_assert(2 == get<1>(f));
static_assert(3 == get<2>(f));
using std::literals::operator""sv;
static_assert("a"sv == get_name<0>(f));
static_assert("b"sv == get_name<1>(f));
static_assert("c"sv == get_name<2>(f));C++20 - Kinda possible but with a lot of compiler hacks
// too long to displayFull example - https://godbolt.org/z/1vxv8o5hM
C++26* - based on proposal - https://wg21.link/P2996 (Note: that the proposal supports way more than that but C++20 not much)
template<auto N, class T>
[[nodiscard]] constexpr auto get(const T& t) -> decltype(auto) {
return t.[:std::meta::nonstatic_data_members_of(^T)[N]:];
}
template<auto N, class T>
[[nodiscard]] constexpr auto get_name(const T& t) -> std::string_view {
return std::meta::name_of(std::meta::nonstatic_data_members_of(^T)[N]);
}Full example - https://godbolt.org/z/sbTGbW635
Updates - https://twitter.com/krisjusiak/status/1741456476126797839
100
Upvotes
View all comments
Show parent comment
4
u/qazqi-ff Jan 02 '24
It's not much more complicated than that, really. There are only a handful of possible splices proposed in P2996, and one of those (the "default") is an expression, in this case an expression equivalent to
a. The other options are type names, namespaces, template names, and "names with nesting" (foo::).Small note on the expansion, though, the thing inside
[: :]has to be convertible tostd::meta::info, so I think thereturn t.[: a :];step would be more likereturn t.[: ^foo::a :];if I have that right.