My question is what is the advantage of perfect forwarding a function, which is passed to our wrapper.
template<typename T, typename ...U>
auto time_function(T&& func, U&& ...args)
{
std::cout<<"timing void function"<<std::endl;
//std::forward<T>(func)(std::forward<U>(args)...); //this vs next one
func(std::forward<U>(args)...);
std::cout<<"timing over"<<std::endl;
}
In the case of argument forwarding, it is clear that forwarding preserves the lvalueness vs rvalueness of the argument. However, is there any use to forward func before calling?
Let's say I pass both temporary functors and normal functions to the time_function wrapper.
Suppose that I have a stateful assignor functor. The assignor will be reused multiple times, so it has to copy the value each time. However, if the assignor is an rvalue, it can just move the value:
struct Assignor {
std::string value;
void operator()(std::string& dest) const &
{
dest = value;
}
void operator()(std::string& dest) &&
{
dest = std::move(value);
}
};
Now, perfect forwarding makes a difference on rvalues:
Assignor f{std::string(10000, 'X')};
std::string a, b, c;
time_function(f, a); // copies the string
time_function(std::move(f), b); // should move the string
// but copies if you don't std::forward
time_function(Assignor{std::string(10000, 'Y')}, c); // same
(This is just an example of how a functor can be optimized w.r.t. value category. I know it looks a bit artificial, but people always come up with creative ideas.)
By the way, you should be using std::invoke
instead of directly calling ()
:
std::invoke(std::forward<T>(func), std::forward<U>(args)...);