I am trying to capture a variadic lambda argument inside a inner lambda and use it there. As an example, consider this code:
int main () {
auto first = [&] (auto&&... one) {
auto second = [&] (auto&&... two) {
return ((one * two) + ...);
};
return second(one...);
};
return first(5);
}
This works with gcc9 but fails with clang8 (https://godbolt.org/z/i2K9cK).
A way to make the code compile is to explicitly capture [&one...]
, but i was wondering whether this is a bug in clang.
Also interesting: Changing the return statement to something where one
is directly expanded (before combining with two
), this compiles again:
return (((one * ...) * two) + ...);
I have found this related post, but the bug declared there seems to be fixed in clang8.
GCC usually produces faster code if you target x86/x86-64. For ARM the situation is ambiguous, often Clang optimizes better. Also, AFAIK Clang does not support optimization for code size.
GCC and Clang have always been trying to prove who has the better error diagnostics. Clang first dissed GCC in their “Expressive Diagnostics”article. GCC improved their diagnostics and released their comeback article, titled “Clang Diagnostics Comparison”.
Clang clearly won here, with MSVC in second. GCC didn't recognize the second error, and the "expected ';' before 'return'" errors from MSVC and GCC are like saying that to climb a tree, I must put the tree below me. It is technicallytrue, but it is stupid.
Of course there are differences, for example LLVM enables auto-vectorizer at -O2 while GCC only enables it by default at -O3, however How come Clang in the last two years have caught up with GCC in version numbers?
This is a bug in Clang. It has been reported. Per comment:
Fixed in r362358.
(Side note: Clang seems to have difficulty with pack-expansions in captures in general. Let's roll out our own version of the closure type generated for the generic lambda first
:
struct __closure_first {
template <typename... Args>
auto operator()(Args&&... one) const
{
auto second = [&] (auto&&... two) {
return ((one * two) + ...);
};
return second(one...);
}
};
Clearly, this is not a real closure type, and non-closure local classes cannot have member function templates. Putting this in the global scope, GCC still works and Clang still fails.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With