This article declares using C++ Lambdas to be "cheap": Lambdas aren't magic - part 2
They demonstrate how to pass lambdas to existing std functions / templates. One article demonstrates how to use "auto" as return type of a function to return a lambda without using std::function.
No article I saw demonstrates making your own functions, esp. class member functions, which take a lambda or more, without using std::function.
So this bold declaration of "lambdas are cheap" - is it really true, in real world scenarios?
As a reference: "Cheap" is to me in this particular quest to sort this out: Sensibly usable on embedded bare metal projects with few hundreds kilobytes of memory and double digit MHz speeds. (I have been using a sane subset of C++ in that realm and am looking for what else I can use)
From what I saw, std::function<> is not cheap. Lambdas passed as a std::function apparently can't get inline optimized anymore, for one thing. But worse, a std::function<> is 32 bytes big. Also apparently, if more than fits in there is captured, dynamic allocation might be used? That all sounds like bad news.
So while I was looking for ways to use lambdas without std::function, and only found one example returning auto, I tried this: I have made a very simple class that uses "auto" for argument types in member functions, and the compiler seemed happy with it (though it's not as "self documenting" code as with std::function with regards to expected functor arguments).
struct FuncyClass
{ unsigned func(auto fnx)
{ return 2 * fnx(7);
}
};
int main()
{ FuncyClass fc;
auto result = fc.func( [](auto x){return x*3;} );
printf("Result: %u\n", result);
return 0;
}
// Output: "Result: 42"
But I have a feeling that this very simple scenario is not showing me possible compiler error floods to come when this gets used by more complicated scenarios. I do not deeply understand what is going on behind the scenes with this syntax, what the compiler does when determining, from the usage of the functor, what arguments and return type are expected, and how this function with auto arguments is implemented under the hood.
Is that, i.e. using auto typed args, really a sensible way of making your class member functions lambda-customizable? Then it would seem "cheap", as at leats in my test the executable was considerably smaller when using auto instead of std::function.
It's still limtied, of course: There is no way for a class to hold on to a lambda without using std::function<> (or a DIY wrapper of similar sort), right? Would it be possible to prevent dynamic allocations from ever happening, e.g. making it a compile-time error when a scenario arises that would require std::function to allocate memory?
std::function
is not, but you are not required to use it. Non-capturing lambdas are convertible to function pointers, capturing lambdas can be passed as templates.std::function
is expensive because it uses type erasure. A lambda is just a short hand functor and those are "cheap" in comparison. You can make your class a template and give it the lambda's type to avoid usingstd::function
.std::sort
, etc.) do so without usingstd::function
. They use templates.std::function
) then the code is easier to use, but you pay a performance penalty.