Perfect forwarding
- C++ course
- Advanced
- Lesson 10/83
- 5 min
Learn argument forwarding with perfect forwarding.
Perfect forwarding
Perfect forwarding passes a function's arguments to another function unchanged: lvalues stay lvalues, rvalues stay rvalues. It uses a universal reference T&& and std::forward<T>.
Example: template <typename T> void wrapper(T&& x) { impl(std::forward<T>(x)); } Here T&& accepts both lvalues and rvalues; std::forward<T> preserves the value category. This avoids unnecessary copies in wrapper functions.
Universal reference
A universal reference is a reference of the form T&& during template parameter deduction. For an lvalue argument T = X&; for an rvalue T = X. A single parameter thus accepts both.
This behavior only applies during template deduction. A concrete type like int&& x accepts only rvalues. Universal references appear in std::vector's push_back(T&&) and emplace_back(Args&&...) member functions.
Practice Write the wrapper template
Let template <typename T> void impl(T&& x) have body std::cout << x;. Then write template <typename T> void wrapper(T&& x) whose body calls impl(std::forward<T>(x));. In main call wrapper(42);.
Starter code
#include <iostream>
#include <utility>
// Write the impl and wrapper templates
int main() {
// Call wrapper with 42
return 0;
}Sample solution
#include <iostream>
#include <utility>
template <typename T>
void impl(T&& x) {
std::cout << x;
}
template <typename T>
void wrapper(T&& x) {
impl(std::forward<T>(x));
}
int main() {
wrapper(42);
return 0;
}Expected output
42
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Match each piece to its role
| Term | Meaning |
|---|---|
T&& x |
Universal reference |
std::forward<T>(x) |
Preserves value category |
Args&&... args |
Variadic universal pack |
std::forward<Args>(args)... |
Forwards the pack |
2 Complete the std::forward line
template <typename T>
void wrapper(T&& x) {
impl(____);
}
template <typename T>
void wrapper(T&& x) {
impl(std::forward<T>(x));
}
Explanation: std::forward<T>(x) preserves value category.
3 Which is used for perfect forwarding?
- std::move
- std::forward Correct answer
- std::swap
- std::copy
Explanation: std::forward preserves value category when forwarding.