Skip to content
  • Forwarding References & std::forward · C++

Forwarding References & std::forward

LearnViaNotes @learnvianotes· 2 min read

A template parameter T&& is a forwarding reference: it binds to lvalues and rvalues alike. std::forward<T> passes the argument on with its original value category, so moves stay moves and copies stay copies.

Reference collapsing

ArgumentT deduced asT&& becomes
lvalue int xint&int& && → int&
rvalue 42 / std::move(x)intint&&

Rule: & &, & && and && & collapse to &; only && && stays &&. A T&& is a forwarding reference only when T is being deduced (a template parameter or auto&&) — std::string&& is a plain rvalue reference.

The problem std::forward solves

C++
#include <iostream>
#include <string>
#include <utility>

void consume(const std::string&) { std::cout << "copy\n"; }
void consume(std::string&&)      { std::cout << "move\n"; }

template <typename T>
void wrapperBad(T&& arg) { consume(arg); }                    // a named variable is an lvalue!

template <typename T>
void wrapperGood(T&& arg) { consume(std::forward<T>(arg)); }  // restores the category

int main() {
    std::string s = "x";
    wrapperBad(s);              wrapperBad(std::string("t"));
    wrapperGood(s);             wrapperGood(std::string("t"));
}
Output
copy
copy
copy
move
std::move(x)std::forward<T>(x)
What it doesUnconditionally casts to rvalueCasts to rvalue only if the original argument was an rvalue
Use withObjects you own and are done withForwarding references T&& in templates

Real use: emplace

C++
#include <iostream>
#include <string>
#include <vector>

struct Order {
    std::string item;
    int qty;
    Order(std::string i, int q) : item(std::move(i)), qty(q) { std::cout << "construct\n"; }
    Order(const Order& o) : item(o.item), qty(o.qty) { std::cout << "copy\n"; }
    Order(Order&& o) noexcept : item(std::move(o.item)), qty(o.qty) { std::cout << "move\n"; }
};

int main() {
    std::vector<Order> orders;
    orders.reserve(4);
    orders.push_back(Order("pen", 2));     // construct a temporary, then move it in
    orders.emplace_back("ink", 1);         // forwards the arguments: construct in place
}
Output
construct
move
construct

What is perfect forwarding?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report