Case 1 :
Consider the following pack expansion in lambda noexcept
specifier:
template <bool... B>
auto g() {
([]() noexcept(B) {}, ...);
}
Clang and MSVC accept this code, but GCC rejects with:
error: expansion pattern '<lambda>' contains no parameter packs
Is this a valid code? Which Compiler should I trust?
Case 2 :
Consider the following pack expansion in lambda requires-clause
:
template <bool... B>
auto g() {
([](auto) requires(B) {}, ...);
}
In this case, Clang and MSVC still accept this code, and GCC rejects it with the same error message. Is this just the same bug?
Case 3 :
Consider the following pack expansion in the lambda template list:
template <typename... Args>
void g(Args...) {
([]<Args>(){}, ...);
}
This time three compiler all reject with the same error message:
expansion pattern '<lambda>' contains no parameter packs
Is there a difference compared to case 1? Or is this a common bug?
Interesting exercise, Looking at the C++20 draft. the standard first distinguishes generic lambdas (7.5.5:5):
A lambda is a generic lambda if the lambda-expression has any generic parameter type placeholders (9.2.8.5), or if the lambda has a template-parameter-list .
int i = [](int i, auto a) { return i; }(3, 4); // OK: a generic lambda int j = []<class T>(T t, int i) { return i; }(3, 4); // OK: a generic lambda
Therefore, case 1 has non-generic lambdas and 2 and 3 have generic lambdas. It does not differentiate between type and non-type template parameters, so I think I agree with Yakk - Adam Nevraumont, all three should be admissible.
Lambdas are represented by an unnamed, unique closure type having a function call operator ( operator()
) (template in case of a generic lambda), whose signature and constraints are determined by the lambda expression. The compiler could definitely satisfy each case with code resembling the following:
template<bool B>
struct closure {
auto operator()() const noexcept(B) {}
};
template <bool... B>
auto g() {
(closure<B>{}, ...);
}
template<bool B>
struct closure {
auto operator()(auto) const requires(B) {}
};
template <bool... B>
auto g() {
(closure<B>{}, ...);
}
template<typename T>
struct closure {
template<T>
auto operator()() const {}
};
template <typename... Args>
void g(Args...) {
(closure<Args>{}, ...);
}
These all compile on my machine, currently with gcc 11.2.1.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.