tower120
tower120

Reputation: 5255

C++11 inline lambda functions without template

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.

Upvotes: 13

Views: 4704

Answers (1)

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();
}

Upvotes: 12

Related Questions