<개요>
std::move 이후, std::forward 와 완벽 전달 (perfect forwarding) 에 대해 작성합니다 |
<Forwarding Problem>
우리가 수 많은 class를 만들었다고 합시다. 그런데 그 class가 너무 많아 차라리 팩토리 함수를 하나 만들어서 생성해주면 편할 것 같군요
팩토리 함수는 Factory(U& arg) 형으로 선언돼있습니다. 상수인 1은 const int& 형이기때문에 올수가 없죠 (또는 int&&) 그래서 팩토리 함수를 하나 더 추가해 오버로딩 해주기로 했습니다.
좋습니다. 이제 aa와 bb를 둘다 만들 수 있게 됐습니다. 이걸로 끝인걸까요?만약 인자가 2개인 class가 새로 추가된다면요?, 그 인자가 따로 const int& 형과 int& 형을 받는다면?새로운 데이터 타입이 추가되고 그것이 const T& 형 또는 T& 형 의 생성자라면?각각의 인자에 맞춰 Factory를 lvalue 형과 rvalue 형을 오버로딩 해줘야 할것이고, 한 클래스당 최소 2개의 팩토리 템플릿을 오버로딩 해줘야 할것입니다. 이를 막기위해 C++11 부턴 rvalue reference가 나왔습니다.
aa는 팩토리 템플릿에 들어가 U& &&arg 형으로 변할 것이고 이는 U& arg 형입니다. bb는 팩토리 템플릿에 들어가 U&& &&arg 형으로 변할 것이고 이는 U&& arg 형입니다. (잘 모르시겠다면 std::move 글 참조)
자 이제 다 고쳐진걸까요? 아니요 하나가 더 남았습니다. std::move 때도 말씀 드렸지만, rvalue가 함수내에 들어가 인자로 사용되게 되면 그 rvalue는 lvalue로 변한다고 적어놨습니다. 그럼 bb를 만들땐 rvalue로 넘겼지만, 생성자로 만들땐 lvalue로 사용되는 겁니다. 만약 B가 rvalue를 가지고 생성을 하고있었다면 절때 들어가지 않겠죠
아마 bb가 생성될 땐, 자동으로 만들어낸 기본 생성자를 호출하여 생성할 것입니다. 저희가 원한건 이게 아닌 rvalue 생성자를 원했는데요. 이때 사용되는데 std::forward 함수입니다. 이 함수는
이렇게 선언되어 있습니다. 즉, lvalue가 넘어왔을땐 static_cast<Ty& &&> 로 캐스팅돼 static_cast<Ty&> 형으로 넘어가게 되고 rvalue가 넘어왓을땐 static_cast<Ty&& &&> 로 캐스팅돼 static_cast<Ty&&> 형으로 넘어가게 됩니다.
return new T(static_cast<U&&>(arg)) 를 사용하셔도 되지만, 좀 더 직관적으로 보이기 위해 return new T(std::forward<U>(arg)) 같은 std::forward를 사용하시는게 좋습니다.
하아 공부하면서 작성하니 이해가 쏙쏙 오네요. 다음은 람다식에 대해 작성하겠습니다. 인용 :http://msdn.microsoft.com/en-us/library/dd293668.aspx |
'C++ > Modern' 카테고리의 다른 글
C++11) decltype (형식 지정자) (1) | 2019.02.03 |
---|---|
C++11) 람다식 (Lambda Expression) 과 std::function (4) | 2019.02.02 |
c++11) std::move (move semantics) (2) | 2019.02.01 |
C++11) auto 키워드 (0) | 2019.01.30 |
C++11) 범위 기반 for문 (loop) (4) | 2019.01.27 |