CodeBlanks Logo Icon CodeBlanks

Perfect forwarding

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

main.cpp
#include <iostream>
#include <utility>

// Write the impl and wrapper templates

int main() {
    // Call wrapper with 42
    return 0;
}

Sample solution

main.cpp
#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

Question
template <typename T>
void wrapper(T&& x) {
    impl(____);
}
Answer
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.

All lessons in Advanced