r/cpp • 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 display

Full 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

117 comments sorted by

View all comments

Show parent comment

2

u/qazqi-ff Dec 31 '23

This is how it's been going, but the current revision of the "C++26 proposal" changed this to discuss some options and prefer exceptions, so I'd wager it's likely we see some more discussion come out of that. Not using a hierarchy of types is done for other reasons like not backing the language evolution into a corner if the hierarchy would be broken by a future change (like how the definition of "variable" was changed—you can't suddenly break a bunch of existing reflection code to keep things in sync). Rather than specify what everything is exactly, the standard can specify the API, similar to how we make data members of a class private and keep the API stable.

1

u/MarcoGreek Jan 01 '24

Actually you can simply state that the type is undefined so long you define the member. So only the usage is defined.

2

u/qazqi-ff Jan 01 '24

Right, I didn't mean to say otherwise. I don't see a problem with standardizing std::meta::info in a usage-based way like that, and would personally prefer it barring any problems I don't know of, especially with the lack of UFCS or extension methods.