ibe
ibe

Reputation: 185

Variadic templates argument fowarding

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

Answers (2)

Tim
Tim

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

Brian Bi
Brian Bi

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

Related Questions