Namespaces
Variants

std::forward

С ru.cppreference.net
 
 
Библиотека утилит
Поддержка языка
Поддержка типов (базовые типы, RTTI)
Макросы тестирования возможностей библиотеки (C++20)
Программные утилиты
Функции с переменным числом аргументов
Поддержка корутин (C++20)
Поддержка контрактов (C++26)
Трёхстороннее сравнение
(C++20)
(C++20)(C++20)(C++20)    
(C++20)(C++20)(C++20)

Общие утилиты
Реляционные операторы (устарело в C++20)
 
Определён в заголовке <utility>
template< class T >
T&& forward( typename std::remove_reference<T>::type& t ) noexcept;
(1) (начиная с C++11)
(до C++14)
template< class T >
constexpr T&& forward( std::remove_reference_t<T>& t ) noexcept;
(начиная с C++14)
template< class T >
T&& forward( typename std::remove_reference<T>::type&& t ) noexcept;
(2) (начиная с C++11)
(до C++14)
template< class T >
constexpr T&& forward( std::remove_reference_t<T>&& t ) noexcept;
(начиная с C++14)
1) Передаёт lvalue как lvalue или как rvalue, в зависимости от T.

Когда t — это пересылающая ссылка (аргумент функции, объявленный как rvalue-ссылка на cv-неквалифицированный параметр шаблона функции), эта перегрузка передаёт аргумент другой функции с той категорией значения, которую он имел при передаче вызывающей функции.

Например, если используется в обёртке, подобной следующей, шаблон ведёт себя, как описано ниже:

template<class T>
void wrapper(T&& arg)
{
    // arg is always lvalue
    foo(std::forward<T>(arg)); // Forward as lvalue or as rvalue, depending on T
}
  • Если вызов wrapper() передаёт rvalue std::string, то T выводится как std::string (не std::string&, const std::string& или std::string&&), и std::forward гарантирует, что в foo будет передана rvalue-ссылка.
  • Если вызов wrapper() передаёт const lvalue std::string, то T выводится как const std::string&, и std::forward гарантирует, что в foo будет передана const lvalue-ссылка.
  • Если вызов wrapper() передаёт не-const lvalue std::string, то T выводится как std::string&, и std::forward гарантирует, что в foo будет передана не-const lvalue-ссылка.
2) Передаёт rvalue как rvalue и запрещает передачу rvalue как lvalue.

Эта перегрузка позволяет передавать результат выражения (например, вызова функции), который может быть rvalue или lvalue, как исходную категорию значения аргумента пересылающей ссылки.

Например, если обёртка не просто передаёт свой аргумент, а вызывает функцию-член для аргумента и передаёт её результат:

// transforming wrapper
template<class T>
void wrapper(T&& arg)
{
    foo(forward<decltype(forward<T>(arg).get())>(forward<T>(arg).get()));
}

где тип arg может быть

struct Arg
{
    int i = 1;
    int  get() && { return i; } // call to this overload is rvalue
    int& get() &  { return i; } // call to this overload is lvalue
};

Попытка передать rvalue как lvalue, например, путём инстанцирования формы (2) с типом lvalue-ссылки T, является ошибкой времени компиляции.

Примечания

См. вывод аргументов шаблона для специальных правил, касающихся пересылающих ссылок ( T&& используемых в качестве параметра функции), и пересылающие ссылки для дополнительных деталей.

Параметры

t - объект для пересылки

Возвращаемое значение

static_cast < T && > ( t )

Сложность

Константа.

Пример

Данный пример демонстрирует идеальную передачу параметра(ов) в аргумент конструктора класса T . Также показана идеальная передача пачек параметров.

#include <iostream>
#include <memory>
#include <utility>
struct A
{
    A(int&& n) { std::cout << "rvalue overload, n=" << n << '\n'; }
    A(int& n)  { std::cout << "lvalue overload, n=" << n << '\n'; }
};
class B
{
public:
    template<class T1, class T2, class T3>
    B(T1&& t1, T2&& t2, T3&& t3) :
        a1_{std::forward<T1>(t1)},
        a2_{std::forward<T2>(t2)},
        a3_{std::forward<T3>(t3)}
    {}
private:
    A a1_, a2_, a3_;
};
template<class T, class U>
std::unique_ptr<T> make_unique1(U&& u)
{
    return std::unique_ptr<T>(new T(std::forward<U>(u)));
}
template<class T, class... U>
std::unique_ptr<T> make_unique2(U&&... u)
{
    return std::unique_ptr<T>(new T(std::forward<U>(u)...));
}
auto make_B(auto&&... args) // since C++20
{
    return B(std::forward<decltype(args)>(args)...);
}
int main()
{
    auto p1 = make_unique1<A>(2); // rvalue
    int i = 1;
    auto p2 = make_unique1<A>(i); // lvalue
    std::cout << "B\n";
    auto t = make_unique2<B>(2, i, 3);
    std::cout << "make_B\n";
    [[maybe_unused]] B b = make_B(4, i, 5);
}

Вывод:

rvalue overload, n=2
lvalue overload, n=1
B
rvalue overload, n=2
lvalue overload, n=1
rvalue overload, n=3
make_B
rvalue overload, n=4
lvalue overload, n=1
rvalue overload, n=5

Смотрите также

(C++11)
преобразует аргумент в xvalue
(шаблон функции)
преобразует аргумент в xvalue, если конструктор перемещения не выбрасывает исключений
(шаблон функции)