Compare the following two situations:
template<class... Args>
void f1(Args&&... args) { do_smth(std::forward<Args>(args)...); }
auto f2 = [](auto&&... args) { do_smth(std::forward<decltype(args)>(args)...); };
If there any difference in the type that will be passed to std::forward or not?
In my understanding, when you specify a forwarding reference using T&&, && is not "matched" against the passed argument, but rather, it's a way to "store" the "original reference" information into T (T will be &, const &, && or const && according to the value category of the passed argument), and then such "original reference" information is combined with && to calculate the final reference type using the usual & + && = & rules, etc.
What I don't know is if decltype(args) will resolve to the type "before" or "after" such computation, or if the resulting type will be ever different from the "original reference", and so if there's any difference in the type specified for std::forward in f1 and f2.
NOTE: I can't use C++20 and template lambdas are outside the question.
Tis never deduced as an rvalue reference. It can be deduced as a non-reference though (for rvalue arguments), possibly const.After, of course.
Which means when (the imaginary)
Tis non-reference,decltypereceivesT &&instead. Butstd::forwardtreatsTandT &&in the same way, so your usage is ok.Moreover, you don't even need
forwardand can just usedecltype(args)(args)(a cast to thedecltyped type), though some prefer to spell out the redundantstd::forwardfor clarity.