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.
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