slartibartfast
slartibartfast

Reputation: 4428

Can you declare a lambda variable without auto and/or templates?

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

Answers (4)

HolyBlackCat
HolyBlackCat

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

Jan Schultke
Jan Schultke

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

Todd Gardner
Todd Gardner

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

David Alber
David Alber

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

Related Questions