1 // RUN: %clang_cc1 -std=c++20 -verify %s
2 // [temp.deduct.p9]
3 // A lambda-expression appearing in a function type or a template parameter is
4 // not considered part of the immediate context for the purposes of template
5 // argument deduction.
6 // [Note: The intent is to avoid requiring implementations to deal with
7 // substitution failure involving arbitrary statements.]
8 template <class T>
__anonc5a543d20102() 9 auto f(T) -> decltype([]() { T::invalid; } ());
10 void f(...);
test_f()11 void test_f() {
12 f(0); // expected-error@-3 {{type 'int' cannot be used prior to '::'}}
13 // expected-note@-1 {{while substituting deduced template arguments}}
14 // expected-note@-5 {{while substituting into a lambda expression here}}
15 }
16
17 template <class T, unsigned = sizeof([]() { T::invalid; })>
18 void g(T);
19 void g(...);
test_g()20 void test_g() {
21 g(0); // expected-error@-4 {{type 'int' cannot be used prior to '::'}}
22 // expected-note@-4 {{in instantiation of default argument}}
23 // expected-note@-2 {{while substituting deduced template arguments}}
24 // expected-note@-7 {{while substituting into a lambda expression here}}
25 }
26
27 template <class T>
__anonc5a543d20202() 28 auto h(T) -> decltype([x = T::invalid]() { });
29 void h(...);
test_h()30 void test_h() {
31 h(0);
32 }
33
34 template <class T>
__anonc5a543d20302() 35 auto i(T) -> decltype([]() -> typename T::invalid { });
36 void i(...);
test_i()37 void test_i() {
38 i(0);
39 }
40
41
42 // In this example, the lambda itself is not part of an immediate context, but
43 // substitution to the lambda expression succeeds, producing dependent
44 // `decltype(x.invalid)`. The call to the lambda, however, is in the immediate context
45 // and it produces a SFINAE failure. Hence, we pick the second overload
46 // and don't produce any errors.
47 template <class T>
48 auto j(T t) -> decltype([](auto x) -> decltype(x.invalid) { } (t)); // #1
49 void j(...); // #2
test_j()50 void test_j() {
51 j(0); // deduction fails on #1, calls #2.
52 }
53