I found that lvalue
lambda closures can always be passed as rvalue
function parameters.
See the following simple demonstration.
#include <iostream>
#include <functional>
using namespace std;
void foo(std::function<void()>&& t)
{
}
int main()
{
// Case 1: passing a `lvalue` closure
auto fn1 = []{};
foo(fn1); // works
// Case 2: passing a `lvalue` function object
std::function<void()> fn2 = []{};
foo(fn2); // compile error
return 0;
}
Case 2 is the standard behavior (I just used a std::function
for demonstration purposes, but any other type would behave the same).
How and why does case 1 work ? What is the state of fn1
closure after the function returned ?
How and why does case 1 work ?
Invoking foo
requires an instance of std::function<void()>
that binds to an rvalue reference. std::function<void()>
can be constructed from any callable object that is compatible with the void()
signature.
Firstly, a temporary std::function<void()>
object is constructed from []{}
. The constructor used is #5 here, which copies the closure into the std::function
instance:
template< class F > function( F f );
Initializes the target with
std::move(f)
. Iff
is a null pointer to function or null pointer to member,*this
will be empty after the call.
Then, the temporary function
instance is bound to the rvalue reference.
What is the state of fn1 closure after the function returned ?
Same as before, because it was copied into a std::function
instance. The original closure is unaffected.
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