Ce face std::forward
În C++ o valoare poate fi o variabilă cu nume (lvalue, care trebuie copiată) sau un temporar (rvalue, care poate fi mutat, adică i se pot „fura” resursele, fără copiere). std::move transformă orice în rvalue. std::forward este varianta condiționată.
Într-un șablon cu parametru T&& arg (numit „referință universală”), std::forward<T>(arg) dă mai departe argumentul exact cum a venit: dacă apelantul a dat un temporar, se mută; dacă a dat o variabilă, se copiază. Aceasta se numește „perfect forwarding”.
Așa funcționează std::make_unique, emplace_back și alte funcții care trimit argumentele unui constructor.
Parametri
| Parametru | Descriere |
|---|---|
T |
Tipul dedus al parametrului de șablon (scris explicit: std::forward<T>). |
arg |
Parametrul de transmis mai departe. |
Ce returnează
Argumentul, ca rvalue dacă a fost primit ca rvalue, altfel ca lvalue.
Exemple
Exemplul 1: Ce vede funcția finală
#include <print>
#include <string>
#include <utility>
void primeste(const std::string&) { std::println("copie (lvalue)"); }
void primeste(std::string&&) { std::println("mutare (rvalue)"); }
template <class T>
void intermediar(T&& arg) {
primeste(std::forward<T>(arg));
}
int main() {
std::string nume = "Ana";
intermediar(nume); // variabilă cu nume
intermediar(std::string("Ion")); // temporar
intermediar(std::move(nume)); // marcat explicit pentru mutare
}
Rezultat
copie (lvalue)
mutare (rvalue)
mutare (rvalue)
Exemplul 2: O funcție de tip make
creeaza trimite argumentele constructorului fără copii inutile, ca std::make_unique.
#include <memory>
#include <print>
#include <string>
#include <utility>
struct Client {
std::string nume;
int varsta;
Client(std::string n, int v) : nume(std::move(n)), varsta(v) {}
};
template <class T, class... Args>
std::unique_ptr<T> creeaza(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
int main() {
auto c = creeaza<Client>("Elena", 31);
std::println("{}, {} ani", c->nume, c->varsta);
}
Rezultat
Elena, 31 ani
Greșeli frecvente
- Folosești
std::forwardfără argument de șablon (std::forward(arg)). Nu compilează: tipulTtrebuie scris explicit. - Transmiți același argument cu
std::forwardde două ori. După prima transmitere, obiectul poate fi deja mutat (gol). - Folosești
std::forwardîntr-o funcție care nu este șablon. Acolo nu există „referință universală”; pentru mutare foloseștestd::move.
Comenzi înrudite
std::move: Mută elementele unui interval la o destinație, fără să le copieze (versiunea din <algorithm>).std::exchange: Pune o valoare nouă într-o variabilă și returnează valoarea veche.std::make_unique: Creează un obiect pe heap și returnează un std::unique_ptr care îl deține.template: Scrie o funcție sau o clasă o singură dată, pentru orice tip; compilatorul generează varianta potrivită pentru fiecare tip folosit.