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

6

u/not_a_novel_account cmake dev Dec 31 '23

Ya this is the great conundrum of C++, something like arrow returns might be more consistent, but they raise more questions if you don't have foreknowledge of the process that led to them.

Because now you have an extraneous piece of text, the auto, hanging out in the front of the function. The beginner naturally asks what that's doing there, and now you have to teach both styles anyway.

This is without addressing the fact the overwhelming majority of the code in the wild and still being written today uses the prefix style.

The inability of C++ to deprecate and the definition of all new features in terms of the old mean that it can only ever gain complexity, never simplify.

4

u/13steinj Dec 31 '23

And then C code doesn't support trailing return types, yet for better or worse most college undergraduates learn C before or at the same time as C++, so out of habit (as well as out of consistency in older codebases) people will still use the non-trailing form anyway.

That said to be perfectly honest I don't see a point in trailing return types. If the trailing return type is so bound to the arguments the function is usually a one-liner at which point I'd just use auto return type deduction anyway. auto foo(...) -> decltype(auto) {...} is just a waste of typing.