Code as below or on godbolt compiles with gcc and MSVC but fails with clang. I couldn't find if/where it is forbidden in the standard. In my opinion it should be supported.
So who is correct on this, clang or gcc/MSVC?
#include <type_traits>
void foo() {
static_assert(decltype([_=std::declval<int>()]() consteval noexcept { // clang error: declval() must not be used
if constexpr (std::is_integral<decltype(_)>::value) {
return std::bool_constant<true>();
} else {
return std::bool_constant<false>();
}
}())::value);
}
The example could be expanded into 3 cases as below or on godbolt:
- as lambda call argument: OK with clang/gcc/MSVC
- as lambda capture: OK with gcc/MSVC, error with clang
- in lambda body: error with clang/gcc/MSVC
So it seems clear that it is not legal in lambda body but legal outside as caller argument. It is not clear if it is allowed in capture list.
#include <type_traits>
auto foo_lambda_argument() {
return decltype([](auto _) noexcept {
return std::bool_constant<std::is_integral<decltype(_)>::value>();
}(std::declval<int>()))::value; // OK with clang/gcc/MSVC
}
auto foo_capture_list() {
return decltype([_=std::declval<int>()]() noexcept { // OK with gcc/MSVC; clang error: declval() must not be used
return std::bool_constant<std::is_integral<decltype(_)>::value>();
}())::value;
}
auto foo_lambda_body() {
return decltype([]() noexcept {
auto _=std::declval<int>(); // clang/gcc/MSVC error
return std::bool_constant<std::is_integral<decltype(_)>::value>();
}())::value;
}