class Knight
{
public:
Knight() { cout << "기본 생성자" << endl; }
Knight(const Knight&) { cout << "복사 생성자" << endl; }
Knight(Knight&&) noexcept { cout << "이동 생성자" << endl; }
};
void Test_RValueRef(Knight&& k)
{
}
int main()
{
Knight k1;
Test_RValueRef(k1); // Error : only r-value
Test_RValueRef(std::move(k1)); // okay(r-value casting)
}
// && 는 무조건 오른값 참조일까?
// Nope!
template<typename T>
void Test_ForwardingRef(T&& param) // 이건 r-value 참조인가? -> 전달 참조이다.
{
}
int main()
{
Knight k1;
Test_ForwardingRef(std::move(k1)); // okay : T = Knight&&
Test_ForwardingRef(k1); // okay : T = Knight&
auto&& k2 = k1; // auto&& : Knight&
auto&& k3 = std::move(k1); // auto&& : Knight&&
// l-value가 들어가면 l-value가 되고
// r-value가 들어가면 r-value가 된다.
}
단, 이건 안됨
template<typename T>
void Test_ForwardingRef(const T&& param) // const붙을시 동작하지 않음
{
}
// ...
Test_ForwardingRef(std::move(k1)); // error
Test_ForwardingRef(k1); // error
근데 이건 언제쓰나?
// 여기서 시작한다
// Func라는 함수를 만들예정인데 r, l value를 모두 받고 싶다면? 함수를 매번 여러 개씩 만들어야 할까?
template<typename T, typename U>
void Func(T&& param, U&& param) // 이렇게 쓸거라면 4개를 만들어야하나???
{
}
forwarding reference를 쓰자!
template<typename T>
void Test_ForwardingRef(T&& param)
{
// ...
// 만약 내부에서 다른 함수를 호출한다면?
Test_Copy(param); // T&&가 뭐일지 알고 넘기나???
}
// 우선 오른값과 오른값 참조의 차이를 알고 가자
void Test_RValueRef(Knight&& k)
{
}
Knight& k4 = k1; // 왼값 참조
Knight&& k5 = std::move(k1); // 오른값 참조
Test_RValueRef(k4); // error : 오른값만 받는다
Test_RValueRef(k5); // error : 역시 오른값만 받는다(참조 안돼)
Test_RValueRef(std::move(k5)); // okay : 오른값으로 만들어줘야한다.
다시 돌아가서
Test_RValueRef(std::move(k1));
template<typename T>
void Test_ForwardingRef(T&& param) /*param 자체는 왼값이다.*/
{
// ...
Test_Copy(param); // param이 복사되며 복사생성자가 호출되게 된다.
Test_Copy(std::move(param)); // 이동 생성자가 호출된다.
}
// 이건 오른값이 Test_ForwardingRef로 들어왔을때고 왼값이 들어온다면?
Test_RValueRef(k1);
template<typename T>
void Test_ForwardingRef(T&& param)
{
// ...
Test_Copy(std::move(param)); // error : 왼값을 함부러 move를 해선안된다.
}
// Test_Copy에 어떻게 넘겨야할까???
// 모두 가능
Test_RValueRef(k1);
Test_RValueRef(std::move(k1));
template<typename T>
void Test_ForwardingRef(T&& param)
{
// ...
Test_Copy(std::forward<T>(param)); // 이건 그냥 받아들이자 forward를 써야한다고
// 왼값 참조면 복사
// 오른값 참조면 이동
}