Open rbock opened 3 years ago
I believe the pack splicing stuff we're working on will help with this; I'll try to follow up when that's ready.
Thanks, looking forward to it!
Bit late to this, but in theory this should already be possible by using a good old sequence expansion, like :
template <class T>
consteval meta::info refl(){
return reflexpr(T);
}
template <std::size_t... Idx>
consteval meta::info make_ctor(std::integer_sequence<std::size_t, Idx...>){
return fragment struct {
template <class... Args>
tuple(Args&&... args) : unqualid("mem_", Idx){args}... {} // parallel expansion
};
}
template <class... Ts>
struct tuple {
consteval {
constexpr std::array<meta::info, sizeof...(Ts)> members = {refl<Ts>()...};
for (unsigned k = 0; k < sizeof...(Ts); ++k){
-> fragment struct {
typename (%{members[k]}) unqualid("mem_", %{k});
};
}
-> make_ctor(std::make_index_sequence<sizeof...(Ts)>{});
}
};
In practice however this doesn't compiles, I think constructors injection aren't supported yet? (funnily enough, this is exactly how the constructors of tuples implemented with variadic inheritance looks like : just a double pack expansion).
There are a few problems there, but (I think) this should work (looks like we have a bug with checking member-initializers too soon):
template <class T>
consteval meta::info refl(){
return reflexpr(T);
}
template <std::size_t... Idx>
consteval meta::info make_ctor(std::integer_sequence<std::size_t, Idx...>){
return fragment struct tuple {
template <class... Args>
tuple(Args&&... args) : unqualid("mem_", Idx){args}... {} // parallel expansion
};
}
template <class... Ts>
struct tuple {
consteval {
constexpr std::array<meta::info, sizeof...(Ts)> members = {refl<Ts>()...};
for (unsigned k = 0; k < sizeof...(Ts); ++k){
-> fragment struct {
typename (%{members[k]}) unqualid("mem_", %{k});
};
}
}
consteval -> make_ctor(std::make_index_sequence<sizeof...(Ts)>{});
};
Neat.
Also @rbock I just realized something : for this particular case you don't need a constructor at all. A tuple implemented this way is just a plain old aggregate, so there is no need for the dozen of constructors of std::tuple anymore :) (I also tried to make a tuple constructor at some point and this is just hitting me now... pretty funny how we can get anchored in our ways)
@groundswellaudio Good point, but this one still needs to be a constructor, and I guess it is not that different to write?
template <class... UTypes>
tuple( tuple<UTypes...>&& other );
Yes, it could be implementable in the same way. But if you declare a constructor, you lose the ability to treat the type as an aggregate and emplace members easily (i wish we had some better mechanism for that). I think a better way to do this would be to implement a conversion operator, also using a pack expansion :
template <class... Us, std::size_t... Idx>
consteval meta::info make_conversion_op(std::integer_sequence<std::size_t, Idx...>){
return fragment this {
return { static_cast<Us>( unqualid("mem_", Idx) )... };
};
}
template <class... Ts>
struct tuple {
static constexpr std::array<meta::info, sizeof...(Ts)> members = {refl<Ts>()...};
consteval {
for (unsigned k = 0; k < sizeof...(Ts); ++k){
-> fragment struct {
typename (%{members[k]}) unqualid("mem_", %{k});
};
}
}
template <class... Us>
operator tuple<Us...>(){
consteval {
-> make_conversion_op<Us...>(std::make_index_sequence<sizeof...(Ts)>{});
}
}
};
This currently crash the compiler on the P1240r2 trunk on godbolt ("error: cannot compile this scalar expression yet") however, but i think the logic is sound. It comes with a few caveats about bracket initialization syntax, but there are some workarounds.
@groundswellaudio I just noticed that I never answered. Using a conversion operator instead certainly is a nice idea.
I am anxiously waiting for new iterations on the new syntax (ideally with metaprogramming) to experiment with :-)
Hi,
I am having a hard time writing tuple constructors using reflection and/or metaprogramming. With metaprogramming, you can imagine structs as
How would I write the variadic constructors? For instance
I was thinking of constructing something like
And then use that to generate something like
I believe this should be possible. But I currently fail to see how to do it?
I cannot use fragments to create such lists as far as I can tell. And I might miss something when trying to use pack expansion...
Cheers,
Roland