Date: Mon, 21 Nov 2022 11:21:51 -0500
On Sun, Nov 20, 2022 at 3:32 PM Lénárd Szolnoki wrote:
> On 20 November 2022 16:59:16 GMT, Arthur O'Dwyer wrote:
> >
> >That sounds useful, and IIUC could be implemented in userspace simply
> like this:
> > template<class T, class... Args>
> > concept StaticallyInvocable = requires (T t, Args&&... args) {
> > t(std::forward<Args>(args)...);
> > T::operator()(std::forward<Args>(args)...);
> > };
> >At first I thought this would misbehave for types where the static and
> >non-static operators do different things [...]
> >but happily Godbolt tells me that those are both ambiguous —
> >`T::operator()(s)` will still do overload resolution among *all* the
> >`operator()`s, and then, if the best-matching one turns out to be
> >non-callable (e.g. because it is non-static and you failed to provide an
> >object to operate on), it'll just hard-error. This is similar to how
> >overload resolution works for constructors (if the best-matching
> >constructor for an implicit conversion turns out to be `explicit`).
>
> This is only true for copy list init. For regular copy init the explicit
> constructors are not included in the overload set.
>
Well, well! Today I learned. Thanks.
// https://godbolt.org/z/PErj5GG6Y
struct A {};
struct B {};
struct C : A, B {};
struct D { D(A); explicit D(B); };
C c;
D d1 = c; // OK (!!)
D d2 = {c}; // Error, ambiguous
D d3() { return c; } // OK (!!)
–Arthur
> On 20 November 2022 16:59:16 GMT, Arthur O'Dwyer wrote:
> >
> >That sounds useful, and IIUC could be implemented in userspace simply
> like this:
> > template<class T, class... Args>
> > concept StaticallyInvocable = requires (T t, Args&&... args) {
> > t(std::forward<Args>(args)...);
> > T::operator()(std::forward<Args>(args)...);
> > };
> >At first I thought this would misbehave for types where the static and
> >non-static operators do different things [...]
> >but happily Godbolt tells me that those are both ambiguous —
> >`T::operator()(s)` will still do overload resolution among *all* the
> >`operator()`s, and then, if the best-matching one turns out to be
> >non-callable (e.g. because it is non-static and you failed to provide an
> >object to operate on), it'll just hard-error. This is similar to how
> >overload resolution works for constructors (if the best-matching
> >constructor for an implicit conversion turns out to be `explicit`).
>
> This is only true for copy list init. For regular copy init the explicit
> constructors are not included in the overload set.
>
Well, well! Today I learned. Thanks.
// https://godbolt.org/z/PErj5GG6Y
struct A {};
struct B {};
struct C : A, B {};
struct D { D(A); explicit D(B); };
C c;
D d1 = c; // OK (!!)
D d2 = {c}; // Error, ambiguous
D d3() { return c; } // OK (!!)
–Arthur
Received on 2022-11-21 16:22:04