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/rvalue | Yes (with deduced T) | Always rvalue |
| Typical use | Generic wrappers | Ownership transfer |
Related posts
- Move semantics
- Universal reference
Keywords
C++, perfect forwarding, std::forward, rvalue, templates