Reputation: 4428
What's the notation for declaring a lambda variable, or function parameter, without the use of auto
or templates? Is there any way to do so? Or does the compiler define a unique class object for each lambda whose name is unknown to the programmer before compile time? If so, why? Can't they just be passed as some sort of function pointer? It would be a major disappointment if that were not possible.
Upvotes: 66
Views: 58561
Reputation: 96013
No, the type of each lambda is unique and unnamed, so there's nothing you could replace auto
with without at least some change in semantics.
std::function
(and other std::..._function
classes) have overhead, only use them if you need the ability to select one of several lambdas at runtime.
Function pointers should have no overhead, but can only point to capture-less lambdas, as explained in the other answers.
Upvotes: 0
Reputation: 39405
What's the notation for declaring a lambda variable, or function parameter, without the use of
auto
or templates?
You could rely on the fact that capture-less lambdas are convertible to function pointers, like this:
void(*f)() = [] { };
If the lambda captures anything, you can also store it in std::function
or the better, modern alternatives std::copyable_function
and std::move_only_function
.
Or does the compiler define a unique class object for each lambda whose name is unknown to the programmer before compile time?
Yes, this happens no matter what. Every lambda expression has a closure type by definition, which is a "unique, unnamed non-union class type". It's simply how lambda expressions work; the fact that they're actually of class type with some call operator makes it possible to store captures in the lambda, which is something a function pointer cannot do.
A capture-less lambda could theoretically result in a function pointer directly instead of being convertible to one (see [expr.prim.lambda.closure] p9), but this would make lambdas with/without captures behave in a radically different way, and that would be confusing and annoying.
Upvotes: 0
Reputation: 13521
Lambdas may hold state (like captured references from the surrounding context); if they don't, they can be stored in a function pointer. If they do, they have to be stored as a function object (because there is no where to keep state in a function pointer).
// No state, can be a function pointer:
int (*func_pointer) (int) = [](int a) { return a; };
// One with state:
int b = 3;
std::function<int (int)> func_obj = [&](int a) { return a*b; };
Upvotes: 62
Reputation: 18091
You can use a polymorphic wrapper for a function object. For example:
#include <functional>
std::function<double (double, double)> f = [](double a, double b) { return a*b };
Upvotes: 26