Reputation: 185
Say I have a function foo()
with takes advantage of c++ variadic templates feature. Now, what's the difference between these implementations:
template <typename... Args>
void foo(Args... args) {
whatever(args...);
}
template<typename... Args>
void foo(Args&... args) {
whatever(args...);
}
template<typename... Args>
void foo(Args... args) {
whatever(&args...);
}
template<typename... Args>
void foo(Args&&... args) {
whatever(std::forward<Args>(args)...);
}
Upvotes: 1
Views: 82
Reputation: 1527
template <typename... Args>
void foo(Args... args) {
whatever(args...);
}
foo
gets copies of args
and passes them to whatever
as l-values.
template<typename... Args>
void foo(Args&... args) {
whatever(args...);
}
foo
gets l-value references to args
and passes them to whatever
as l-values.
template<typename... Args>
void foo(Args... args) {
whatever(&args...);
}
foo
gets copies of args
and passes them to whatever
as pointers to l-values. Be careful of object lifetimes here.
template<typename... Args>
void foo(Args&&... args) {
whatever(std::forward<Args>(args)...);
}
foo
gets forwarding references to args
. Whether they are l-values or r-values depends on what happens at the call site. They are then perfect-forwarded to whatever
, preserving their reference type. Scott Meyers originally called these "universal" references, but forwarding reference is the preferred terminology now.
Upvotes: 2
Reputation: 119069
The first one takes its arguments by value. The second one takes its arguments by lvalue reference (so non-const
rvalues cannot be used). The third one also takes its arguments by value, but passes pointers to whatever
. The fourth one takes its arguments by forwarding reference and perfect-forwards them to whatever
.
There is nothing magical about the variadic templates; the rules are the same as if there were only one argument.
Upvotes: 2