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.
All lambdas are inline. Not all calls to them are necessarily inlined.
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; };
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.
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.
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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With