Reputation: 119877
I have come across two variants of std::forward
usage with variadic template arguments.
template <typename... Args>
void foo(Args&&... arga)
{
bar(std::forward<Args>(args)...); // variant 1
bar(std::forward<Args...>(args)...); // variant 2
// EDIT the above is a fixed version, the initial incorrect version was
// bar(std::forward<Args>(args...)); // variant 1
// bar(std::forward<Args...>(args...)); // variant 2
}
I have tried both variants with g++ and clang, and both appear to work equally well. No warnings produced with -Wall -Wextra -Wpedantic
.
Are both variants correct? If not, why not? What does the standard have to say about it?
Upvotes: 3
Views: 1815
Reputation: 171303
bar(std::forward<Args>(args)...); // variant 1
This is correct.
bar(std::forward<Args...>(args...)); // variant 2
This is wrong.
If the parameter pack is empty variant 1 expands to bar()
which is valid, but variant 2 expands to bar(std::forward<>())
which is ill-formed because forward
is missing its parameters.
If the pack has one element both variants expand to bar(std::forward<T>(t))
which is valid.
If the pack has two elements variant 1 correctly expands to bar(std::forward<T1>(t1), std::forward<T2>(t2))
which is valid. But for two elements variant 2 expands to bar(std::forward<T1, T2>(t1, t2))
which is ill-formed because std::forward
has one template parameter and one function parameter.
So in all cases variant 1 works, but variant 2 is only valid for the case of a parameter pack with one element (and if you only care about a single template argument you shouldn't be using a variadic template at all!)
Basically a pack expansion should be PATTERN...
where pattern is the thing you want to be repeated for each element in the pack. Since you want to call std::forward<T>(t)
for each element, the PATTERN should be std::forward<Args>(args)
and so the full pack expansion is that followed by ...
(and not something with the ...
inside the PATTERN, which results in two separate pack expansions, one of the types in Args
and one of the variables in args
).
Upvotes: 16