I know this could seem very stupid for non-noob C++
developers, but what are the differences between these 4 lambda expressions?
Code:
#include <iostream>
#include <math.h>
#include <functional>
inline double MyFunction(double a, double b, double c) {
return (a + b + c);
}
inline void FunctionWrapper(std::function<double(double)> tempFunct, double value) {
std::function<double(double)> funct;
funct = tempFunct;
std::cout << "result: " << funct(value) << std::endl;
}
int main()
{
double value = 100.0;
FunctionWrapper([](double value) { return MyFunction(value, 1.0, 2.0); }, value);
FunctionWrapper([](double value) -> double { return MyFunction(value, 1.0, 2.0); }, value);
FunctionWrapper([value](double value) { return MyFunction(value, 1.0, 2.0); }, value);
FunctionWrapper([value](double value) -> double { return MyFunction(value, 1.0, 2.0); }, value);
}
It seems it does the same? Either using two different "notations" and using the value as closure?
In this context, they all produce the same results. However, there are logical differences between them.
[](double value) { return MyFunction(value, 1.0, 2.0); }
This is a lambda which takes a single parameter of type value
and passes this into MyFunction
. Its return type is deduced from the return
statement to be that of MyFunction
, which is double.
[](double value) -> double { return MyFunction(value, 1.0, 2.0); }
This is the same lambda as before, but this time its return type is explicitly specified to be double
. It's the same in this case, but it would be different from the first one if the return type of MyFunction
was something else. In that case, the first one would return what MyFunction
returns, while this one would still return double
.
[value](double value) { return MyFunction(value, 1.0, 2.0); }
This one depends on the standard version used. In C++11 and 14, this one captures main
's local variable value
. However, that capture is hidden by the lambda's parameter value
, so it's effectively useless. It would be different if the lambda had been declared as e.g. [value](double v) { return MyFunction(value, 1.0, 2.0); }
. This would have passed on the captured value
, and not its parameter.
In C++17 and above, this was changed and it's actually ill-formed (compilation error). Naming a lambda parameter the same as something you capture is no longer allowed.
Since the change was a defect report (CWG 2211), it applies retroactively and so it's legal for compilers to reject such code even in earlier C++ versions.
[value](double value) -> double { return MyFunction(value, 1.0, 2.0); }
Same as lambda number 3, with explicit return type specification (the difference between 3 and 4 is exactly the same as between 1 and 2).
The second lambda differs from the first in that you've specified the return type explicitly. Since the deduced return type of the first lambda is the same, there is no difference.
The third and fourth lambdas are ill-formed, since they declare a parameter with same name as a capture. See the standard rule:
[expr.prim.lambda.capture]
If an identifier in a simple-capture appears as the declarator-id of a parameter of the lambda-declarator's parameter-declaration-clause, the program is ill-formed. [ Example:
void f() { int x = 0; auto g = [x](int x) { return 0; } // error: parameter and simple-capture have the same name }
— end example ]
This wording was adopted in C++17.
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