Использование универсальных ссылок

Универсальные ссылки — это ссылки, которые могут быть либо lvalue, либо rvalue в зависимости от контекста. Они определяются с использованием шаблонов и синтаксиса T&&.

template <typename T>
void foo(T&& arg) {
    // arg может быть как lvalue, так и rvalue
}

Ещё по теме: Универсальные ссылки.


Использование std::forward

Функция std::forward используется для передачи параметров в их первоначальном виде (как lvalue или rvalue) при вызове других функций.

Пример без идеальной передачи

#include <iostream>
 
void process(int& x) {
    std::cout << "Lvalue: " << x << std::endl;
}
 
void process(int&& x) {
    std::cout << "Rvalue: " << x << std::endl;
}
 
template <typename T>
void foo(T&& arg) {
    process(arg);  // всегда вызывает process(int&)
}
 
int main() {
    int a = 5;
    foo(a);        // вызывает process(int&)
    foo(5);        // вызывает process(int&)
    return 0;
}

В этом примере аргумент всегда передается как lvalue, что не всегда желательно.

Пример с идеальной передачей

#include <iostream>
#include <utility> // для std::forward
 
void process(int& x) {
    std::cout << "Lvalue: " << x << std::endl;
}
 
void process(int&& x) {
    std::cout << "Rvalue: " << x << std::endl;
}
 
template <typename T>
void foo(T&& arg) {
    process(std::forward<T>(arg));  // сохраняет тип и значение arg
}
 
int main() {
    int a = 5;
    foo(a);        // вызывает process(int&)
    foo(5);        // вызывает process(int&&)
    return 0;
}

std::forward используется для сохранения типа и значения аргумента, что позволяет правильно вызвать перегруженные функции.