In the following code, what happens at runtime?
while ( ([]()->bool { return something(); })() ) {
...
}
- The lambda instance is created only once and reused in subsequent iterations.
- Every iteration creates a new instance, that is only used once.
- None of the above (please explain).
Initially it seems obvious to me that it's re-created in every iteration, but I wonder if the compiler does some kind of optimization.
First a couple of standard quotes, with my emphasis:
[stmt.while]/1
In the while statement the substatement is executed repeatedly until
the value of the condition ([stmt.select]) becomes false. The test
takes place before each execution of the substatement.
[expr.prim.lambda]/2
A lambda-expression is a prvalue whose result object is called the
closure object.
The above tells use that ([]()->bool { return something(); })()
is evaluated before every iteration. And that the sub-expression []()->bool { return something(); }
creates a prvalue. So it springs to life only during the evaluation of the full expression.
So the dry letter of the law would indicate it's a different object of the closure type that is constructed and destructed every time the condition is evaluated.
But compilers are not stupid. I believe that under the as-if rule it's more than likely to be optimized into a direct call to something()
. That is because the construction and destruction of the lambda does not have observable side effects.
And if we indeed use a tool like the godbolt online compiler viewer, we see that GCC 7.2 at -O1
will call the function directly. And so does Clang 5.0, but I had to crank optimizations to -O2
for that to happen.