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