I have the following code which is used to call a function on an object and pass any argument in a perfect-forwarding way
template <typename F, typename T>
inline auto call_with_args(F&& f, T&& t) {
return [f = std::forward<F>(f), t = std::forward<T>(t)]
(auto&&... args) mutable { return (t.*f)(std::forward<decltype(args)>(args)...); };
}
I'm trying to read this but I'm unsure what [f = std::forward<F>(f)]
does. That is the 'capture by value' syntax, but what does that have to do with std::forward
(which is a cast to rvalue reference from what I could read)? Is it re-defining f
with a new variable which gets assigned whatever type and value category f
had after being universal-reference-bound to the function parameter f
?
Can somebody explain this to me in simple terms please?
f
and t
are what as known as forwarding references and like all references, they are considered an lvalue, even if they refer to an rvalue.
So, since they are lvalues if you just captured them by value like
return [f, t](...) { ... };
Then f
and t
will be copied into the closure object as they are lvalues. This isn't great as we are missing out on being able to move f
and t
if they refer to rvalues . To avoid this we use std::forward
which cast rvalues back to rvalues while leaving lvalues as lvalues.
That gives you the syntax of
return [f = std::forward<F>(f)](...) { ... };
which says create a member of the lambda named f
and initialize it with std::forward<F>(f)
where that f
is the f
from the surrounding scope.