52 lines
1.9 KiB
C++
52 lines
1.9 KiB
C++
// RUN: %clang_cc1 -std=c++20 -verify %s
|
|
// [temp.deduct.p9]
|
|
// A lambda-expression appearing in a function type or a template parameter is
|
|
// not considered part of the immediate context for the purposes of template
|
|
// argument deduction.
|
|
// [Note: The intent is to avoid requiring implementations to deal with
|
|
// substitution failure involving arbitrary statements.]
|
|
template <class T>
|
|
auto f(T) -> decltype([]() { T::invalid; } ());
|
|
void f(...);
|
|
void test_f() {
|
|
f(0); // expected-error@-3 {{type 'int' cannot be used prior to '::'}}
|
|
// expected-note@-1 {{while substituting deduced template arguments}}
|
|
// expected-note@-5 {{while substituting into a lambda expression here}}
|
|
}
|
|
|
|
template <class T, unsigned = sizeof([]() { T::invalid; })>
|
|
void g(T);
|
|
void g(...);
|
|
void test_g() {
|
|
g(0); // expected-error@-4 {{type 'int' cannot be used prior to '::'}}
|
|
// expected-note@-4 {{in instantiation of default argument}}
|
|
// expected-note@-2 {{while substituting deduced template arguments}}
|
|
// expected-note@-7 {{while substituting into a lambda expression here}}
|
|
}
|
|
|
|
template <class T>
|
|
auto h(T) -> decltype([x = T::invalid]() { });
|
|
void h(...);
|
|
void test_h() {
|
|
h(0);
|
|
}
|
|
|
|
template <class T>
|
|
auto i(T) -> decltype([]() -> typename T::invalid { });
|
|
void i(...);
|
|
void test_i() {
|
|
i(0);
|
|
}
|
|
|
|
|
|
// In this example, the lambda itself is not part of an immediate context, but
|
|
// substitution to the lambda expression succeeds, producing dependent
|
|
// `decltype(x.invalid)`. The call to the lambda, however, is in the immediate context
|
|
// and it produces a SFINAE failure. Hence, we pick the second overload
|
|
// and don't produce any errors.
|
|
template <class T>
|
|
auto j(T t) -> decltype([](auto x) -> decltype(x.invalid) { } (t)); // #1
|
|
void j(...); // #2
|
|
void test_j() {
|
|
j(0); // deduction fails on #1, calls #2.
|
|
}
|