std::forward
Определено в заголовке <utility> |
||
|---|---|---|
| (1) | ||
template< class T > T&& forward( typename std::remove_reference<T>::type& t ) noexcept; |
(с C++11) (до C++14) |
|
template< class T > constexpr T&& forward( std::remove_reference_t<T>& t ) noexcept; |
(с C++14) | |
| (2) | ||
template< class T > T&& forward( typename std::remove_reference<T>::type&& t ) noexcept; |
(с C++11) (до C++14) |
|
template< class T > constexpr T&& forward( std::remove_reference_t<T>&& t ) noexcept; |
(с C++14) |
Когда 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()передает rvaluestd::string, тогдаTвыводится какstd::string(а неstd::string&,const std::string&, илиstd::string&&), иstd::forwardгарантирует, что вfooпередается ссылка на rvalue. - Если вызов
wrapper()передает const lvaluestd::string, тогдаTвыводится какconst std::string&, иstd::forwardгарантирует, что вfooпередается ссылка на const lvalue. - Если вызов
wrapper()передает non-const lvaluestd::string, тогдаTвыводится какstd::string&, иstd::forwardгарантирует, что вfooпередается ссылка на non-const 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) |
получает ссылку на rvalue (шаблон функции) |
|
(C++11) |
получает ссылку на rvalue, если конструктор перемещения не выбрасывает исключение (шаблон функции) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/utility/forward