// P2036R3 - Change scope of lambda trailing-return-type // PR c++/102610 // { dg-do compile { target c++23 } } // From LLVM's test/SemaCXX/lambda-capture-type-deduction.cpp template constexpr bool is_same = false; template constexpr bool is_same = true; void f () { int y; static_assert(is_same decltype((x)) { return x; }())>); static_assert(is_same decltype((x)) { return x; }())>); static_assert(is_same decltype((y)) { return y; }())>); static_assert(is_same decltype((y)) { return y; }())>); // Clang++ rejects this one, though the only difference is the extra (), // and without the () the result is correct, as demonstrated above. static_assert(is_same decltype((y)) { return y; }())>); static_assert(is_same decltype((y)) { return y; }())>); static_assert(is_same decltype((y)) { return y; }())>); static_assert(is_same decltype((y)) { return y; }())>); auto ref = [&x = y]( decltype([&](decltype(x)) { return 0; }) y) { return x; }; } void nested () { int x, y, z; (void)[&]( decltype([&]( decltype([=]( decltype([&]( decltype([&](decltype(x)) {})) {})) {})) {})){}; (void)[&]( decltype([&]( decltype([&]( decltype([&]( decltype([&](decltype(y)) {})) {})) {})) {})){}; (void)[=]( decltype([=]( decltype([=]( decltype([=]( decltype([&] {})) {})) {})) {})){}; } void test_noexcept () { int y; static_assert(noexcept([x = 1] noexcept(is_same) {}())); static_assert(noexcept([x = 1] mutable noexcept(is_same) {}())); static_assert(noexcept([y] noexcept(is_same) {}())); static_assert(noexcept([y] mutable noexcept(is_same) {}())); static_assert(noexcept([=] noexcept(is_same) {}())); static_assert(noexcept([=] mutable noexcept(is_same) {}())); static_assert(noexcept([&] noexcept(is_same) {}())); static_assert(noexcept([&] mutable noexcept(is_same) {}())); } void check_params () { int i = 0; int &j = i; [=](decltype((j)) jp, decltype((i)) ip) { static_assert(is_same); static_assert(is_same); static_assert(is_same); static_assert(is_same); }; [=](decltype((j)) jp, decltype((i)) ip) mutable { static_assert(is_same); static_assert(is_same); static_assert(is_same); static_assert(is_same); static_assert(is_same); static_assert(is_same); }; [a = 0](decltype((a)) ap) mutable { static_assert(is_same); static_assert(is_same); static_assert(is_same); decltype(a) x; decltype((a)) y = x; static_assert(is_same); }; [a = 0](decltype((a)) ap) { static_assert(is_same); static_assert(is_same); static_assert(is_same); decltype(a) x; decltype((a)) y = x; static_assert(is_same); }; int a; [a](decltype((a)) ap) mutable { static_assert(is_same); static_assert(is_same); static_assert(is_same); decltype(a) x; decltype((a)) y = x; static_assert(is_same); }; [a](decltype((a)) ap) { static_assert(is_same); static_assert(is_same); static_assert(is_same); decltype(a) x; decltype((a)) y = x; static_assert(is_same); }; } template void check_params_tpl () { T i = 0; T &j = i; (void)[=](decltype((j)) jp, decltype((i)) ip) { static_assert(is_same); static_assert(is_same); // In these two, clang++ produces 'const int&'. Why, when it's // the same as in check_params, just not a template? static_assert(is_same); static_assert(is_same); }; (void)[=](decltype((j)) jp, decltype((i)) ip) mutable { static_assert(is_same); static_assert(is_same); static_assert(is_same); static_assert(is_same); static_assert(is_same); static_assert(is_same); }; (void)[a = 0](decltype((a)) ap) mutable { static_assert(is_same); static_assert(is_same); static_assert(is_same); }; (void)[a = 0](decltype((a)) ap) { static_assert(is_same); static_assert(is_same); static_assert(is_same); }; } template void test_requires () { int x; [x = 1]() requires is_same {} (); [x = 1]() mutable requires is_same {} (); [x]() requires is_same {} (); [x]() mutable requires is_same {} (); [=]() requires is_same {} (); [=]() mutable requires is_same {} (); [&]() requires is_same {} (); [&]() mutable requires is_same {} (); [&x]() requires is_same {} (); [&x]() mutable requires is_same {} (); [x = 1]() requires is_same {} (); [x = 1]() mutable requires is_same {} (); } void use () { test_requires(); check_params_tpl(); }