C++ Perfect Forwarding | Preserve Value Categories

C++ Perfect Forwarding | Preserve Value Categories

이 글의 핵심

How to pass arguments through generic wrappers without extra copies and without losing lvalue/rvalue information.

The problem

Inside wrapper(T&& arg), arg is always an lvalue (it has a name). Calling callee(arg) usually selects lvalue overloads. std::forward<T>(arg) restores the original category.

template<typename T>
void wrapper(T&& arg) {
    callee(std::forward<T>(arg));
}

Reference collapsing recap

See reference collapsing: when T is int&, T&& becomes int&.

Patterns

  • make_unique, make_shared, emplace — all forward constructor arguments.
  • Thread entry points forward functor + args.
  • Logging wrappers forward to the underlying callable.

Multiple forwards

Forwarding the same object twice can “move from” it on the first use—treat moved-from objects carefully; often copy or consume once.

forward vs move summary

std::forward<T>std::move
Preserves lvalue/rvalueYes (with deduced T)Always rvalue
Typical useGeneric wrappersOwnership transfer

  • Move semantics
  • Universal reference

Keywords

C++, perfect forwarding, std::forward, rvalue, templates