When is using a Lambda a good idea?
Lambdas are good when you have a tiny block of code that needs to be used as a parameter to something.
A common example is the comparison function to the enormous number of functions that take a comparison function. Various sorting algorithms require a sorting predicate, a function that tells how two values sort relative to each other. Some of these were so common they were built into C, such as strcmp(). Finding the min or max, sorting the various ordered containers, merging, finding ranges in sorted containers, all of these are great for a lambda:
myContainer.sort( [](const Thing&a, const Thing&b) -> bool {
return a.whatever > b.whatever;
});
They are also great for other types of predicate functions. Searches are one of many of these uses:
find(iter.begin(), iter.end(), [](const thing&a) -> bool { return a.matches_search == true;});
Since these are templates the compiler cam optimize the entire block of code, including the condition, into something much nicer than the original.
Lambdas were originally fancy hidden function object objects, so they required a tiny bit of space and an anonymous type name. They were still functions, so they were a block of code that was compiled somewhere and had an address to a function with a return value.
You could get much -- but not all -- of the same functionality by writing a small function with static linkage. For example, you might have a small function:
// Basically the same as the example above, but not quite because this has a name and cannot as easily be inlined
bool ThingCompare(const Thing&a, const Thing&b) {
return a.whatever > b.whatever;
};
Or if you are passing more complex parameters, a function object:
// Basically equivalent to the lambda: [x](int n) { return a < x;}
class Foo {
public:
Foo( int x ) : x(param);
bool operator()(const Thing&a) {
return a < x;
};
private:
int x;
}
There are additional fun options of how parameters are passed with [&](){} and [=](){} style lambdas.
I write that they are basically equivalent, but they are not exactly equivalent.
When they were incorporated to the language formally that restriction was removed since several compiler vendors had already implemented several optimizations on it. As mentioned above, these little blocks of code have an anonymous and unnamable type, they are simply a block of code and not a function or a functor. They may not have a name, and if the compiler can get rid of them they may not even have an address. Although template types could handle them just fine as an unspecified typename, and existing functionality that required function pointers just fine, there were some edge cases that could not handle it. The auto keyword was finally included to handle this strange little type.
Lambdas are great for parameters of template functions when it comes to inlining and optimizing. Instead of having an address to a function call which may or may not be inlined, the compiler has the exact block of code, and it can decide when generating the code if it should be implemented as raw code, or if it should be implemented as a function call, or implemented as something else entirely. It can optimize the code along with the template code, potentially eliminating or reducing the processing work.
My general guide is that if the code is up to two lines of code, it is good as a lambda. If the code is over five lines it is too complex and belongs in a function. If they are 3-5 lines, use your own judgement.