Namespaces
Variants

std:: forward

From cppreference.net
Utilities library
헤더 파일에 정의됨 <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부터)
1) T에 따라 lvalue를 lvalue 또는 rvalue로 전달합니다.

t forwarding reference (cv-unqualified 함수 템플릿 매개변수에 대한 rvalue 참조로 선언된 함수 인자)인 경우, 이 오버로드는 인자를 호출 함수에 전달될 때 가졌던 value category 를 유지한 채 다른 함수로 전달합니다.

예를 들어, 다음과 같은 래퍼에서 사용될 경우, 템플릿은 아래와 같이 동작합니다:

template<class T>
void wrapper(T&& arg)
{
    // arg는 항상 lvalue입니다
    foo(std::forward<T>(arg)); // T에 따라 lvalue 또는 rvalue로 전달
}
  • wrapper() 호출 시 rvalue std::string 이 전달되면, T std::string 으로 추론되며 ( std::string& , const std::string& , 또는 std::string&& 가 아님), std::forward 는 rvalue 참조가 foo 에 전달되도록 보장합니다.
  • wrapper() 호출 시 const lvalue std::string 이 전달되면, T const std::string& 으로 추론되며, std::forward 는 const lvalue 참조가 foo 에 전달되도록 보장합니다.
  • wrapper() 호출 시 non-const lvalue std::string 이 전달되면, T std::string& 으로 추론되며, std::forward 는 non-const lvalue 참조가 foo 에 전달되도록 보장합니다.
2) rvalue를 rvalue로 전달하며, rvalue를 lvalue로 전달하는 것을 금지합니다.

이 오버로드는 (함수 호출과 같은) 표현식의 결과를, rvalue 또는 lvalue일 수 있는, 포워딩 참조 인수의 원래 값 범주로 전달할 수 있게 합니다.

예를 들어, 래퍼가 단순히 인자를 전달하지 않고, 인자에 대해 멤버 함수를 호출하고 그 결과를 전달하는 경우:

// 변환 래퍼
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; } // 이 오버로드에 대한 호출은 rvalue입니다
    int& get() &  { return i; } // 이 오버로드에 대한 호출은 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로 변환
(함수 템플릿)
이동 생성자가 예외를 던지지 않는 경우 인수를 xvalue로 변환
(함수 템플릿)