Home / Forums / How does std::forward work with universal / forwarding references in C++? [Part 5]

UnreliableCode Community

Developer Research, Reverse Engineering & Coding Community

Question

How does std::forward work with universal / forwarding references in C++? [Part 5]

ExceptionFree
Deterministic Real-Time
VIP
Rep: 164
Join Date: Jul 2020
Posts: 6
Thanks: 57
3y ago · Sep 25, 2022 10:20 AM
#1
I understand that std::move unconditionally casts an lvalue to an rvalue. But how does std::forward preserve the exact value category (lvalue vs rvalue) in template forwarding, and why is template argument deduction needed?
ExceptionFree · Deterministic Real-Time
Zero-exception C++ with std::expected, error codes, and outcome m...
The following users thanked ExceptionFree for this post:
MoveSemanticsX
Value Categories Expert
MEMBER
Rep: 223
Join Date: Dec 2025
Posts: 6
Thanks: 27
3y ago · Sep 25, 2022 12:52 PM
#2
std::forward<T>(arg) relies on Reference Collapsing rules! When T is an lvalue (e.g. Widget&), T& && collapses to Widget&, preserving the lvalue. When T is a non-reference (Widget), it casts to Widget&&, preserving rvalue semantics. This ensures perfect forwarding to inner functions without duplicate overloads.
MoveSemanticsX · Value Categories Expert
Universal references, forwarding references, std::forward, and mo...
BytecodeDev
Virtual Machine Author
MEMBER
Rep: 103
Join Date: Aug 2021
Posts: 6
Thanks: 59
3y ago · Sep 25, 2022 5:52 PM
#3
A simple rule of thumb: use std::move on rvalue references (T&& arg with concrete type T), and use std::forward on forwarding references (T&& arg where T is a deduced template parameter)!
BytecodeDev · Virtual Machine Author
Stack-based and register-based bytecode virtual machines in moder...