53 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -verify %s2// [temp.deduct.p9]3// A lambda-expression appearing in a function type or a template parameter is4// not considered part of the immediate context for the purposes of template5// argument deduction.6// [Note: The intent is to avoid requiring implementations to deal with7// substitution failure involving arbitrary statements.]8template <class T>9auto f(T) -> decltype([]() { T::invalid; } ());10void f(...);11void 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 17template <class T, unsigned = sizeof([]() { T::invalid; })>18void g(T);19void g(...);20void 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 27template <class T>28auto h(T) -> decltype([x = T::invalid]() { });29void h(...);30void test_h() {31 h(0);32}33 34template <class T>35auto i(T) -> decltype([]() -> typename T::invalid { });36void i(...);37void test_i() {38 i(0);39}40 41 42// In this example, the lambda itself is not part of an immediate context, but43// substitution to the lambda expression succeeds, producing dependent44// `decltype(x.invalid)`. The call to the lambda, however, is in the immediate context45// and it produces a SFINAE failure. Hence, we pick the second overload46// and don't produce any errors.47template <class T>48auto j(T t) -> decltype([](auto x) -> decltype(x.invalid) { } (t)); // #149void j(...); // #250void test_j() {51 j(0); // deduction fails on #1, calls #2.52}53