Subject: Re: [std-proposals] Std-Proposals Digest, Vol 23, Issue 16
From: Bengt Gustafsson (bengt.gustafsson_at_[hidden])
Date: 2021-02-21 07:41:38
> I think I agree. We should allow this to work:
> template<class F> receiver(F&&) -> detail::corresponding_type<receiver, F>;
> One question would be what happens if the typedef expands to something
> that is not a valid specialization of `receiver` ? e.g. what if it's a
> specialization of a different template, or not-a-template, or
> ill-formed? Is that something like a substitution failure?
I think it should be a hard error, other substitution failures in the
return type should work as for any function call overload resolution but
if after this is all done you end up with a type which is not an
instance of the deduced class template I see no reason to view this as a
substitution failure, it would just cause confusion if deduction guides
that are erroneous just end up being ignored rather than flagged as errors.
>> I can't figure out a workaround that allows me to create a receiver like this given this limitation...
> The Right Answer is to do what `std::function` and `std::function_ref`
> do: instead of `receiver<Ps...>` you should just use
> `receiver<void(Ps...)>`. Then it's easy to write
> template<class F> receiver(F&&) -> receiver< detail::corresponding_sig<F> >;
Right, that may be doable in some cases, but in this particular case I
have a virtual method with the same signature. I removed it just to
minimize the example.
> template<class F> receiver_impl(F&&) -> receiver_impl<
> detail::corresponding_sig<F> >;
> template<class... Ps> using receiver = receiver_impl<void(Ps...)>;
> but I think this doesn't work in C++20; I think you need "CTAD for
> alias templates" before this will have even a hint of working, and
> maybe not even then.
I had an implementation running where the receiver inherited from the
result of a metafunction call which selected different implementations
based on the constructor parameters to the subclass, with variations
depending on if the callable was a function, method+object, lambda or
other callable. It also optimizes the function/method pointer away if it
is provided as a template parameter. I scrapped this in favor of a
std::function based implementation as receivers could otherwise never be
class members as that would require deduction from constructor
parameters (as I noted in the PS of my original post). Thre receiver
class makes most sense as a member in most cases (it is the slot end of
a pure C++ implementation of Qt's signal/slot system).
I cleaned this code up and put it on godbolt just in case anyone likes
to see what in my opinion awesome tricks you can make with modern C++,
but also, sadly, how ridiculously complicated it gets (be warned!):
> By the way, another fantasy feature that would solve your problem is
> if a metafunction could return a first-class pack. Then you could
> write something like
> template<class F> receiver(F&&) -> receiver<
> detail::corresponding_template_args<receiver, F>... >;
> But of course that doesn't help you today.
Yes, this would be a nice application for packs as return types, but the
fairly simple corresponding_type which takes a class template to
instantiate also shows that in at least this case it is fairly easy to
work around not having that.
>> PS: I just found on GodBolt an experimental Clang version called NDSMI which allows auto and CTAD on data members. Does anyone know who did this and if it has a corresponding proposal?
> I vaguely recollect that the auto-NSDMI branch on Godbolt was done by
> Corentin Jabot.
> Yep. Googling "godbolt github auto nsdmi" finds:
> Subject: Digest Footer
> Std-Proposals mailing list
> End of Std-Proposals Digest, Vol 23, Issue 16
STD-PROPOSALS list run by firstname.lastname@example.org
Standard Proposals Archives on Google Groups