简体   繁体   中英

Can I define a C++ lambda function without auto?

I have plenty of C# experience before but I am new to C++. I have seen this problem when trying to use lambda as I used to do.

For example:

auto compare = [] (int i1, int i2) { return i1*2 > i2; }

Is there any way to define the lambda with a specific type, rather than auto deduction?

I am asking this because I want to define a common lambda for my class. This lambada will be used in multiple places so I don't want to define them multiple times. However, 'auto' can only be used on static members, while on the other hand, I want to access non-static fields in the lambda.

You use std::function , which can glob any lambda or function pointer.

std::function< bool(int, int) > myFunc = []( int x, int y ){ return x > y; };

See C++ Reference .

You could use std::function , but if that's not going to be efficient enough, you could write a functor object which resembles what lambdas do behind the scenes:

auto compare = [] (int i1, int i2) { return i1*2 > i2; }

is almost the same as

struct Functor {
    bool operator()(int i1, int i2) const { return i1*2 > i2; }
};
Functor compare;

If the functor should capture some variable in the context (eg the "this" pointer), you need to add members inside the functor and initialize them in the constructor:

auto foo = [this] (int i) { return this->bar(i); }

is almost the same as

struct Functor {
    Object *that;
    Functor(Object *that) : that(that) {}
    void operator()(int i) const { return that->bar(i); }
};
Functor foo(this);

You can use as std::function<Signature> as mentioned, but at the cost of type-erasing the lambda. This will add an indirection (basically a virtual function call) when you call your lambda. So keep in mind it is less efficient if you will use it in a context where this matters.

The way to do this without the overhead of std::function , if you feel a functor is too cumbersome, is to use function pointers, a typedef, and optionally a macro.

In your example, this function pointer would look like this:

bool (*compare)(int, int) = [] (int i1, int i2) { return i1*2 > i2; };
^^^^^^^^^^^^^^^^^^^^^^^^^

Note how compare , the pointer's identifier, is tucked into the parenthesis, this trips people up sometimes, but it's the proper way to declare a function pointer.

You can write a typedef in the same way:

typedef bool (*Compare)(int, int);

The typedef name is where the identifier would ordinarily be. This allows you to now write the more concise:

Compare func = [] (int i1, int i2) { return i1*2 > i2; };
^^^^^^^^^^^^

If you allow yourself to use macros, you can go even further in terms of ergonomics:

#define CompareLambda [](int i1, int i2)
typedef bool (*Compare)(int, int);
...
Compare func = CompareLambda{ return i1*2 > i2;};

Macros and typedefs exist as tools to make your work as a programmer easier by helping you avoid repeating yourself, don't be afraid to use them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM