A code snippet I saw in Effective Modern C++ has a clever implementation of the instrumentation rationale to create a function timer :
auto timeFuncInvocation =
[](auto&& func, auto&&... params)
{
start timer;
std::forward<decltype(func)>(func)(
std::forward<decltype(params)>(params)...);
stop timer and record elapsed time;
};
My question is about std::forward<decltype(func)>(func)(...
- To my understanding, we are actually casting the function to its original type, but why is this needed? It looks like a simple call would do the trick.
- Are there any other cases where we use perfect forwarding to make a function call ?
This looks like a good use case for the use of familiar template syntax in lambda expressions in case we wanted to make the timer type a compile time constant.
A better description of what
std::forward<decltype(func)>(func)(...)
is doing would be preserving the value category of the argument passed to the lambda.Consider the following functor with ref-qualified
operator()
overloads.Remember that within the body of the lambda
func
is an lvalue (because it has a name). If you didn'tforward
the function argument the&&
qualified overload can never be invoked. Moreover, if the&
qualified overload were absent, then even if the caller passed you an rvaluefoo
instance, your code would fail to compile.Live demo