std::forward
| 헤더 <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부터) | |
t이 전달 참조 (cv-한정되지 않은 함수 템플릿 매개변수에 대한 rvalue 참조로 선언된 함수 인자)일 때, 이 오버로드는 인자를 호출 함수에 전달될 때 가졌던 값 종류로 다른 함수에 전달합니다.
예를 들어, 다음과 같은 래퍼에서 사용될 경우 템플릿은 아래에 설명된 대로 동작합니다:
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은 rvalue 참조가foo에 전달되도록 보장합니다.wrapper()에 대한 호출이 const lvaluestd::string를 전달하면,T은const std::string&로 추론되고,std::forward은 const lvalue 참조가foo에 전달되도록 보장합니다.wrapper()에 대한 호출이 비-const lvaluestd::string를 전달하면,T은std::string&로 추론되고,std::forward은 비-const lvalue 참조가foo에 전달되도록 보장합니다.
이 오버로드는 표현식(함수 호출 등)의 결과를 전달 참조 인자의 원래 값 종류로 전달할 수 있게 합니다. 이 결과는 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로 전달하려는 시도, 예를 들어 lvalue 참조 타입 T로 (2) 형식을 인스턴스화하는 것은 컴파일 타임 오류입니다.
참고 사항
자세한 내용은
template argument deduction
에서 전달 참조(
T&&
가 함수 매개변수로 사용되는 경우)에 대한 특별 규칙과
forwarding references
에서 다른 세부 사항을 참조하십시오.
매개변수
| t | - | 전달될 객체 |
반환값
static_cast < T && > ( t )
복잡도
상수.
예제
이 예제는 클래스
T
의 생성자 인자로 매개변수를 완벽 전달(perfect forwarding)하는 방법을 보여줍니다.
또한 매개변수 팩(parameter packs)의 완벽 전달도 함께 보여줍니다.
#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로 변환
(함수 템플릿) |
|
(C++11)
|
이동 생성자가 예외를 던지지 않는 경우 인수를 xvalue로 변환
(함수 템플릿) |