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.
-
1"It would be a major disappointment if that were not possible." Why? How could that possibly be useful?ildjarn– ildjarn2011-11-14 19:33:50 +00:00Commented Nov 14, 2011 at 19:33
-
@ildjarn For runtime lambda!fstamour– fstamour2013-02-18 01:42:26 +00:00Commented Feb 18, 2013 at 1:42
4 Answers
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; };
5 Comments
const char[N] where N is the number of characters in it plus one.std" as "with templates" or not. Remember that std::string is an alias for std::basic_string<char>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 };
Comments
What's the notation for declaring a lambda variable, or function parameter, without the use of
autoor 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.
Comments
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.