Home > Software engineering >  C Forwarding on variadic values which are not rvalue references
C Forwarding on variadic values which are not rvalue references

Time:10-30

Consider:

template <typename... Args>
void foo(Args... args) {
    bar(std::forward<Args>(args)...);
}

template <typename... Args>
void foo2(Args&&... args) {
    bar(std::forward<Args>(args)...);
}

I understand the perfect rvalue references forwarding in case of foo2, but what is the purpose of forwarding the variadic argument values of foo?

What would be different if foo would look like this?

template <typename... Args>
void foo(Args... args) {
    bar(args...);
}

CodePudding user response:

It's not the same thing.

In this

template <typename... Args>
void foo(Args... args) {
    bar(std::forward<Args>(args)...);
}

The two things together sum up to static_cast<Args&&>(args)... having an rvalue reference return type, i.e. returning an rvalue (because Args is not a reference, so no reference collapsing can occur between Args and && to give an lvalue reference return type, which would mean an lvalue return value).

So no, there's no perfect forwarding in your first version of foo. The std::forward in it unconditionally casts its arguments to rvalues; and that's typically std::move's job:

// this is equivalent to the code above
template <typename... Args>
void foo(Args... args) {
    bar(std::move(args)...);
}
  • Related