2 // { dg-do compile { target c++23 } }
4 // SFINAE when the call operator for a lambda with captures is instantiated
5 // with an unrelated type.
6 // diagnose ambiguous overloads when the call operator for a captureless lambda is instantiated
7 // with an unrelated type.
9 // overload resolution from call expression
11 /* [expr.prim.lambda.general-5]
13 Given a lambda with a lambda-capture, the type of the explicit object
14 parameter, if any, of the lambda's function call operator (possibly
15 instantiated from a function call operator template) shall be either:
17 --(5.1) the closure type,
18 --(5.2) a class type derived from the closure type, or
19 --(5.3) a reference to a possibly cv-qualified such type. */
21 // The above wording is similar to [dcl.fct-15] which is handled by SFINAE,
22 // thus we also handle the following cases the same way.
24 // We need the 2 overloads to be ambiguous to observe substitution failure
25 // for the lambda's call operator when instantiated with an unrelated type.
26 // We accomplish this by introducing both overloads through using declarations.
29 void operator()(this auto) {}
36 operator int() const {return {};}
41 auto s0 = S0{[](this auto){}};
42 s0.operator()<int>(); // { dg-error {call of overloaded 'operator\(\)\(\)' is ambiguous} }
44 auto s1 = S0{[x = 42](this auto){}};
45 s1.operator()<int>(); // { dg-bogus {call of overloaded 'operator\(\)\(\)' is ambiguous} }
50 void operator()(this auto&&) {}
56 operator int() const {return {};}
61 auto s0 = S1{[](this auto&&){}};
62 s0.operator()<int>(); // { dg-error {call of overloaded 'operator\(\)\(\)' is ambiguous} }
64 auto s1 = S1{[x = 42](this auto&&){}};
65 s1.operator()<int>(); // { dg-bogus {call of overloaded 'operator\(\)\(\)' is ambiguous} }
70 // needs to be a template, we are explicitly passing a template argument,
71 // without the parameter here this would not be a candidate
72 template<typename U = void>
73 void operator()(this int) {}
80 operator int() const {return {};}
83 // I don't know why the calls to s0::operator() are not ambiguous, it might have to do with one taking less conversions, I'm not sure.
84 // Someone who knows better should remove those cases if they are sure they are actually correct.
88 auto s0 = S2{[](this auto){}};
89 s0.operator()<int>(); // { dg-error {call of overloaded 'operator\(\)\(\)' is ambiguous} {Not sure if this is a bug, one might be a better conversion} { xfail *-*-* } }
91 auto s1 = S2{[x = 42](this auto){}};
92 s1.operator()<int>(); // { dg-bogus {call of overloaded 'operator\(\)\(\)' is ambiguous} }
97 auto s0 = S2{[](this auto&&){}};
98 s0.operator()<int>(); // { dg-error {call of overloaded 'operator\(\)\(\)' is ambiguous} {Not sure if this is a bug, one might be a better conversion} { xfail *-*-* } }
100 auto s1 = S2{[x = 42](this auto&&){}};
101 s1.operator()<int>(); // { dg-bogus {call of overloaded 'operator\(\)\(\)' is ambiguous} }