-
Notifications
You must be signed in to change notification settings - Fork 154
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
is it a way to serialize field names? #90
Comments
Also, this approach allows us to to make field with N names.
Also we can bind a C++ keyword as field name:
|
Continuing the ORM topic.. As a
|
How is is better than a macro then ? struct User {
F(int, id);
F(std::string, login);
}; |
I wrote a demo where gcc and msvc can "extract" the members name without any macro [1], from C++20 standard based on pfr. [1] https://godbolt.org/z/4nGGh6a4f
[2] clang is not fully C++20 compliant. ** but there is a method where "constexpr literal types" works on clang too. See my newer comments. |
@schaumb Fantastic! Just two questions: -Isn't there any UB in manipulating pointers of union non active member? @apolukhin what do you think about it? |
|
Impressive! Just a question, this seems to rely on compiler storing the complete type of the union field in I don't understand how the union's f member captured from the destructured binding of T into a std::tuple still reference the member's name and not its type. Can you explain this part ? |
(note: As a fallback RUNTIME library, it can be use
|
I tried to make it work on clang too, and I succeeded: If someone creates a lib (or PR) from this "hack", please mention me/my github acc. |
@schaumb I think I will create the PR having finished the traveling. I don't know when will it be, maybe in a month. No problem about copyrights, you will be mentioned :) |
Il giorno mar 13 giu 2023 alle ore 15:42 Bela Schaum
***@***.***> ha scritto:
@denzor200
UB: It's all made in compile time, so if there is an UB, the compiler will not compile (or it will crash). The union not active member pointers are not UB as far as I know (at least until its value not read or write)
"Undefined" means that it's not established what happens. It might
crash, it might produce wrong code, or it might also just work, what
happens it's not given. Also, correct me if I am wrong, you are
actually accessing the non-active member, via this line:
auto& [m1, m2, m3] = *ptr;
|
The code is doing this: template<class T>
constexpr auto members() {
// TODO for all 1..N
auto& [m1, m2, m3] = union_val<T>.f;
return std::tuple{&m1, &m2, &m3};
} where template<>
union union_type<XClass>
{
inline constexpr ~union_type() noexcept
{
}
char c = {};
XClass f;
};
template<>
inline constexpr const union_type<XClass> union_val<XClass> = {{}}; It's taking a reference on each member of the structure It works well also with: template <typename T>
union union_type {
constexpr ~union_type() {}
T f = {};
char c;
}; but you'll need to make If I understand correctly, the destructured binding here is perfectly fine, and it's used in PFR also to detect the field type and position/count. IMHO, the only UB is the PRETTY_FUNC and other special macro that aren't standard compliant. But since there is no standard compliant way to capture a type and convert it to its textual representation, I guess that a "compiler driver" code that's worth using. |
[Note] The |
[Note2] @X-Ryl669 The whole union wrapper thing made because not just constexpr initializable structures members can be reflected. |
Yes, I understood this. If @falemagn wanted no UB while using the union, it could have been specialized by the "is_default_constructible" trait (as an additional template parameter that's partially specialized), so in that case, no access to the non-constructed member would be done. But, that way, as you said, you can't reflect non-default-constructible structure. Another option would be to declare a template template <typename T>
union union_type {
constexpr ~union_type() {}
std::reference_wrapper<T> f;
char c;
};
template <typename T>
constexpr T & make_reflector<T>();
template<>
inline constexpr const union_type<XClass> union_val<XClass> = {.f = make_reflector<T>{}};
template<class T>
constexpr auto members() {
// TODO for all 1..N
auto& [m1, m2, m3] = union_val<T>.f;
return std::tuple{&m1, &m2, &m3};
} or even simpler: template <typename T>
constexpr inline std::reference_wrapper<T> ref_val{make_reflector<T>()};
template<class T>
constexpr auto members(T & f) {
// TODO for all 1..N
auto& [m1, m2, m3] = f;
return std::tuple{&m1, &m2, &m3};
}
// To be called as:
members(ref_val<T>) Or something in the same vein. As you said, since the code is never called at runtime, I doubt it would be an issue with UB here, even the way you've written it (and a compiler would warn you if it was). I don't know all the tricks that can be used to create a "virtual" instance of a structure without actually creating any real instance, yet, I was never bit by this in SFINAE code, so I would assume it's pretty safe. |
Thanks @X-Ryl669 ! template <typename T>
extern T obj;
template<class T>
consteval auto members() {
// TODO for all 1..N
auto& [m1, m2, m3] = obj<T>;
return std::tuple{&m1, &m2, &m3};
} Clang prints warning (undefined-var-template), but that can be ignore https://godbolt.org/z/oE7o1Mjx9 or other version if name() returns with a |
Hello everyone! I've posted for review PR based on the "hack" discussed before: #129 |
This issue can be closed because the |
We need to:
field<T, A>
template class, this class is just a wrapper to T withstd::reference_wrapper
-like(??) iface.name
object with overloadedoperator=(std::string_view)
, and this overloaded operator must be constexprThis short example:
https://godbolt.org/z/nT4bdrnKc
Interface of
field_t<T,A>
class is not ideal, but this short example shows that structure with named fields are possible.The text was updated successfully, but these errors were encountered: