std::vector into constexpr std::span (not only std::vector in fact but lets focus on that).// this WON'T compile
// constexpr std::vector nsdm = nonstatic_data_members_of(^^T, std::meta::access_context::unchecked());
// this WILL compile
constexpr std::span nsdm = define_static_array(nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()));
But here lies another issue, a deeper one:
- NTTP argument should be a structured type.
And you know what? Neither
std::span nor std::string_view are structured types! SO you cannot use them as NTTP! And you're forced to use old hacks to transform std::span and std::string_view into std::array, because std::array IS a structured type. Another topic related to this proposal is the behavior of string literals in compile time and how they cannot easily be used as NTTP. Basically, difference between
constexpr char* (string literal, cannot be NTTP) and const char* constexpr (NOT a strign literal, can be NTTP). And this DOES matter when you're trying to use string literals as NTTP (for instance you wanna pass a name of a member as template argument and use it in you reflection). Yes there is a hack with static_string workaround, but static_string is effectively an std::array under the hoods, whereas define_static_string gives you const char* constexpr if I'm not mistaken. And now you have to somehow find a common ground between static_string (aka array) and const char* constexpr...My opinion is that p3491 is broken and
std::span is a bad choise (why not std::array?!). ### We have
template for but we lack some kind of spread functionalitytemplate for is good. But you may also want to spread your std::vector<std::meta::info> and initialize something using fold-expressions for instance (in general, you may want to spread variadic in any of allowed contexts). And here lies another issue: you can't easily do that using built-in C++26 reflection functionality - your are forced my write a hacky wrappers youself (overcoming all these issues with NTTP on the way). Overall constexpr metaprogramming and variadics don't work NICELY together, unfortunately.### You cannot save already evaluated compile-time std::meta::info data into static constexpr member variable of a class if you return it from a consteval function which
define_aggregate insideconsteval {
// this doesn't compile
// static constexpr auto cached_data = define_some_kind_of_aggregate(^^T);
}
This looks straigt up like a bug. I'm not sure why it works this way, and you cannot always be sure regarding such novice topics. But good diagnostics would be helpful...
### Speaking about diagnostics...
They are pretty much non-existent. Yes, I understand that this is an experimental implementation of the proposal, but anyway. All you get is "is not a constant expression" and megabytes of "notes" below. It is just painful. It is MUCH worse than your usual template metaprogramming diagnostics...
Another annoying limitation is:
### You cannot
define_aggregate a struct which is declared outside of your class.I'm pretty sure this is a deliberate choise, but I'm not sure what is the motivation. Maybe someone can decipher this... IMHO it could work just fine - you always can check whether a particular struct needs to be defined or already defined using
std::meta::is_complete_type. Imagine you implement different SoA containers and all of them share same reference type based on original TValue type. You can't do this using current proposal.## Conclusions
C++26 reflection is great. Even in its current state it enables all kinds of cool libraries. But it is not THAT user-friendly as it is advertised. It is still expect-only feature IMHO, it still requires deep