Функция forward
Функция forward из заголовка <utility> выполняет
так называемую идеальную передачу (perfect forwarding). Она
позволяет передать аргумент в другую функцию, сохранив его
исходную категорию значения: lvalue останется lvalue, а rvalue
останется rvalue. В единственный параметр функции передается
значение, которое нужно передать дальше, а в качестве
шаблонного аргумента указывается тип, выведенный через
T&& (универсальная ссылка). Функция возвращает ссылку
на переданный объект с сохранением его категории значения.
Чаще всего forward применяется внутри шаблонных функций
вместе с std::move и универсальными ссылками, чтобы
избежать лишнего копирования и корректно выбирать перегрузки
принимающей функции.
Синтаксис
std::forward<T>(arg)
Пример
Давайте напишем функцию-обертку, которая идеально передает свой аргумент в другую функцию. Сначала передадим lvalue:
#include <iostream>
#include <utility>
using namespace std;
void target(int& x)
{
cout << "lvalue: " << x << endl;
}
void target(int&& x)
{
cout << "rvalue: " << x << endl;
}
template <typename T>
void wrapper(T&& arg)
{
target(forward<T>(arg));
}
int main()
{
int a = 5;
wrapper(a);
wrapper(10);
return 0;
}
Результат выполнения кода:
"lvalue: 5"
"rvalue: 10"
Пример
Давайте посмотрим, что произойдет, если вместо forward
использовать обычную передачу параметра. Аргумент потеряет
свою категорию значения:
#include <iostream>
#include <utility>
using namespace std;
void target(int& x)
{
cout << "lvalue: " << x << endl;
}
void target(int&& x)
{
cout << "rvalue: " << x << endl;
}
template <typename T>
void wrapper(T&& arg)
{
target(arg);
}
int main()
{
int a = 5;
wrapper(a);
wrapper(10);
return 0;
}
Результат выполнения кода:
"lvalue: 5"
"lvalue: 10"
Пример
Давайте используем forward для передачи строки в
конструктор вектора:
#include <iostream>
#include <utility>
#include <vector>
#include <string>
using namespace std;
template <typename T>
void pushToVector(vector<string>& v, T&& value)
{
v.push_back(forward<T>(value));
}
int main()
{
vector<string> res;
string str = "abcde";
pushToVector(res, str);
pushToVector(res, string("12345"));
for (const auto& s : res)
{
cout << s << endl;
}
return 0;
}
Результат выполнения кода:
"abcde"
12345