Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 inline lambda functions without template

Tags:

c++

c++11

lambda

I want to pass lambda function as callback to another function:

void test(const std::function<void()> fn){
    fn();
}

It works, all ok. But. It does not inline it, no matter how high compiler optimization level I use:
proof

And when I play a while, I found, that with template -it becomes inlined:

template<typename T>     
void test2(T fn){
     fn();
}

proof_2

So... Is there any way to make it inlined without templates? And why it becomes inlined with template declaration? Only function type is passing as template argument, not the function itself.

like image 790
tower120 Avatar asked Jan 28 '14 14:01

tower120


People also ask

Are lambda functions inline?

All lambdas are inline. Not all calls to them are necessarily inlined.

What is the correct syntax for lambda expression in C++11?

Lambdas can both capture variables and accept input parameters. A parameter list (lambda declarator in the Standard syntax) is optional and in most aspects resembles the parameter list for a function. auto y = [] (int first, int second) { return first + second; };

Does C have lambda function?

the C standard does not define lambdas at all but the implementations can add extensions. Gcc also added an extension in order for the programming languages that support lambdas with static scope to be able to convert them easily toward C and compile closures directly.

Can lambdas be templated?

From the various lambda improvements, template parameters for lambdas are my favorite ones. Lambdas support with C++20 template parameters, can be default-constructed and support copy-assignment, when they have no state, and can be used in unevaluated contexts.


1 Answers

Short answer: no, you can't make this work without templates (in the general case). The reason is that each lambda expression in your source code generates a unique type for that lambda closure. Proof:

auto f1 = [] { return 1; };
auto f2 = [] { return 1; };
static_assert(!std::is_same<decltype(f1), decltype(f2)>::value, "He's wrong");

Therefore, to accept an arbitrary closure, you either have to use a template, or a type-erasure wrapper (such as std::function). Of course, type erasure relies on runtime polymorphism, so it doesn't lend itself to inlining.

The only way you could potentially make this work is with a stateless lambda (no capture), which has an implicit conversion to a pointer to function. Have your algorithm take the parameter as such a pointer to function, and hope the optimiser sees deep enough to inline the call. In other words, change the function to this:

void test(void (*fn)()) {
    fn();
}
like image 168
Angew is no longer proud of SO Avatar answered Sep 28 '22 00:09

Angew is no longer proud of SO