bloomberg/clang-p2996

std::meta::members_of cannot be called in a constexpr context

Closed this issue · 1 comments

I'm trying to iterate over members of a struct and I can't retrieve the members in a constexpr context. In the P2996 paper, they have this example:

struct member_descriptor
{
  std::size_t offset;
  std::size_t size;
};

template <typename S>
consteval auto get_layout() {
  constexpr auto members = nonstatic_data_members_of(^S);
  std::array<member_descriptor, members.size()> layout;
  for (int i = 0; i < members.size(); ++i) {
      layout[i] = {.offset=offset_of(members[i]), .size=size_of(members[i])};
  }
  return layout;
}

But I can't make it work. Here is a link to the issue: https://godbolt.org/z/zdzKhP94T

Hey @sturcotte06 ! Thanks for the report.

We could do a better job calling this out in the paper, but the example isn't valid with only (C++23 + P2996) - It in fact requires a further change (i.e., P3032 - "Less transient constexpr allocation"), which is on track for C++26 but hasn't yet been voted into the working draft.

I won't be implementing P3032 support on this fork - once it's merged into the working draft, it will eventually be implemented in upstream clang, and we'll pick it up here through a merge from upstream.

Fortunately, the workaround in the meantime is fairly straightforward:

  1. Remove the constexpr on the declaration of members.
  2. Replace members.size() with nonstatic_data_members_of(^S).size() in the declaration of layout.

You can see that working here.