template <typename T>
void myFunction(..., T && callback) {
...
callback(...);
...
}
Is it preferable to use T &&
than T&
or const T&
?
Or even simply T
to pass by value instead of pass by reference.
Does function or lambdas have the concept of lvalue & rvalue? Can I std::move
a function / lambdas?
Does const
of const T&
enforce that the function cannot modify its closure?
Is it preferable to use T && than T& or const T&?
Universal references allow perfect forwarding, so they are often preferable in generic template functions.
Or even simply T to pass by value instead of pass by reference.
This is often preferable when you wish to take ownership.
Does function or lambdas have the concept of lvalue & rvalue?
Yes. Every value expression has a value category.
Can I std::move a function / lambdas?
Yes. You can std::move
pretty much anything.
Another matter is whether std::move
'd object is moved from. And yet another matter is whether an object can be moved. Lambdas are movable unless they contain non-movable captures.
Taking a forwarding reference can make a difference, but you have to call the callback correctly to see it. for functions and lambdas it doesn't matter if they are an rvalue or lvalue, but if you have a functor, it can make a difference
template <typename T>
void myFunction(..., T && callback) {
callback(...);
}
Takes a forwarding reference, and then calls the callback as a lvalue. This can be an error if the function object was passed as an rvalue, and its call operator is defined as
operator()(...) && { ... }
since that is only callable on an rvalue. To make your function work correctly you need to wrap the function name in std::forward
so you call it in the same value expression category it was passed to the function as. That looks like
template <typename T>
void myFunction(..., T && callback) {
std::forward<T>(callback)(...);
// you should only call this once since callback could move some state into its return value making UB to call it again
}
So, if you want to take rvalues and lvalues, and call the operator as an rvalue or lvalue, then the above approach should be used, since it is just like doing the call in the call site of myFunction
.
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