Open SpintroniK opened 6 months ago
Thanks @SpintroniK.
Interesting, thanks for sharing. As far I understand, this is actually deducing the constructor parameters not the members, it just happen that in this examples constructor parameter match the public members. That would break if the constructor had different types as they wouldn't match members, right? I also think that not all constructors needed to be defined, you can just try to find the longest one up to sizesof(struct) or something. For the constructor parameters, there is also a way to deduce the - https://godbolt.org/z/3faKq5x3q.
So I think constructor traits would be a great addition, though not sure about relying on the fact that constructor matches member parameters unless I'm missing something? We would need to be able to somehow guarantee constructors and members are matching? Interested to hear thoughts regarding the approach/concerns?
Very interesting, I like the constructor_traits! Not sure why I needed a default constructor, I think it was related to counting the members of the struct. I need to test that again, but apparently it's not strictly required, so I guess the constructor_traits is the way to go. You're right about not matching the members: https://godbolt.org/z/hM91zzxYM. The only thing that seem to be very important is the number of arguments of the constructor.
Thanks for following-up. It's very interesting how it actually works. Will add constructor traits to reflect.
That would be very nice! I've been wanting to reflect on structs with constructors for a while. Been playing a little bit with the code you shared. This is what I came up with: https://godbolt.org/z/3s14PEv7K with the help of this post Counting the number of fields in an aggregate in C++20.
I didn't keep the code I wrote yesterday, but I think I had to add a default constructor when working with reflect. At first I didn't and got a compile error, not sure why though...
Just an update - https://github.com/qlibs/di supports constructor deduction and injection; there is ctor_traits
which can accomplish that )by default it returns the constructor with the longest number of parameters but potentially it can be a list of all available candidates, it supports value categories too).
Example - https://godbolt.org/z/e98M6eq3q
struct Point
{
Point() {}
Point(int x_, int y_, int z_) : x{x_}, y{y_}, z{z_} {}
Point(int x_, int y_) : x{x_}, y{y_}, z{0} {}
int x;
int y;
int z;
};
template<class...> struct show_type;
int main() {
show_type<di::ctor_traits<Point>::type>{}; // show_type<di::type_list<int, int, int>>
}
That's pretty cool. The constructor with the longest number of parameters seems like a good default. Any chance to have that integrated into reflect to allow reflection on aggregates with constructors?
Yeah, let's add it inot reflect
I've been using this library, and I think it's fantastic. Well done! It looks like things started when this was posted: [C++20] 60 LOC constexpr get_name for members / no ifdefs / clang,gcc,msvc . I've been playing a bit with this example and realized it's possible to get structs name even if a user defined constructor exists. It's also possible to iterate over the members of a struct that has a user defined constructor. So far, getting names and values of a struct's members works if a user defined constructor exists. Of course, it only works if:
foo() = default;
.If I have both constructors, I can do something like:
And it works, I can iterate over all three members and get their names and values. Of course, this means that the
is_aggregate_v
constraint no longer applies, and that the first two constructors need to exist, otherwise it fails to compile.Do you think that's something that could be added to
reflect
to make it work on structs that have user defined constructors?