The example code below prints values from a lambda function, which simply increments and returns the value of a static local counter variable.
It prints 0,1
and 2,3
as expected with gcc and clang with C++17. But not in Visual Studio Community 2017 15.9.3 with /std:c++17
set - it prints 0,0
and 2,3
instead.
#include <iostream>
int main() {
auto f = [] {
static int i = 0;
return i++;
};
const int v1 = f(); // Expect v1 = 0
const int v2 = f(); // Expect v2 = 1
// Prints the wrong values (MSVC 15.9.3 with /std:c++17)
std::cout << v1 << "," << v2 << std::endl; // Expect "0,1", prints "0,0"
// Prints the right values (or ought to with C++17 sequencing, anyway)
std::cout << f() << "," << f() << std::endl; // Expect "2,3", prints "2,3"
return 0;
}
The strange output (in x86 debug builds)
0,0
2,3
It looks like a compiler bug (so we filed the report): https://developercommunity.visualstudio.com/content/problem/347419/unexpected-return-from-lambda-with-static-local-va.html
In what way is the produced program wrong, such that it incorrectly prints 0
for both v1
and v2
, but correctly prints 2, 3
after that? Any educated guess at what the compiler bug is?
As a workaround I used a capture instead:
auto f = [i = 0]() mutable {
return i++;
};
UPDATE - as a side note, the output from the example above is different again in x86 release builds:
0,1
3,2
There is another existing issue with MSVC, where std::cout
's <<
operator is not sequenced left-to-right despite /std:c++17
being set, which I would speculate results in 3,2
being output here, at least.
MSVC compiles the following cleanly:
constexpr int foo() {
static int i = 0;
return i++;
}
static_assert(foo() == foo()); // oh no
That is not standards compliant.
So, what happens is that since C++17, lambdas are implicitly constexpr
if they can be. MSVC wrongly decides that the lambda is constexpr
, and so folds f()
into a constant for v2
(that it got from v1
). It doesn't do this when you directly output it because it apparently doesn't eagerly evaluate constexpr
stuff like gcc does (or uses some other heuristic that we can't know about).
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