A similar question has been asked before, but I'm still confused. The STL, I believe, exclusively passes by value, as passing by reference might have consequences in a multi-threaded environment. Say, when two or more threads are executing a mutable lambda. I currently use a universal reference when I just want to invoke a lambda:
template <typename F>
inline void invoke(F&& f)
{
f();
}
This binds to any function object, just like a const&
would, but maybe it's a bad idea for inlining. Is a lambda passed by copy easier to inline by the compiler? I'd like the passed lambdas to be as "inlinable" as possible.
Think of a lambda as a small object with a function call operator:
int foo = 1000;
auto f = [=]() ->int { return foo; };
is somewhat equivalent to:
class FooLambda {
int foo;
public:
FooLambda(int foo) : foo(foo) {}
int operator()(){ return foo; }
};
// ...
int foo = 1000;
FooLambda f(foo);
So you see, the function body itself can be inlined if it is seen in the same translation unit as it is called (and possibly if not by some smarter compilers). Since your invoke
is a template, it knows the actual type of the lamdba, and you don't force it to jump through function-pointer hoops, which a big inhibitor of inlining.
Taking the callable object by value or reference in invoke
determines whether the captured variables are local to the function body or not, which can make a difference if it means they will be in cache.
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