Info

해당 글에서는 C++에서 사용되는 rvalue형식과 lvalue형식의 함침(collapsing)규칙에 대해서 간단하게 다룬다.

만약 템플릿을 사용해서 타입을 넘겼을 때, 내부적으로 해당 타입을 레퍼런스 형식으로 사용한다고 가정해보자.

template<T>
void test(T&& b) {
	T& a = b;
	...
	...
	...
}
 
int main() {
	test(10);
}

이럴 경우 int&&형식으로 템플릿 내부에서 처리되게 되는데 C++에서는 이때 ‘참조 함침’으로 이를 처리한다.


구체적인 규칙은 다음과 같다.

  • & &&
  • & &&&
  • && &&
  • && &&&&

구체적인 예시는 다음과 같다.

#include <type_traits>
#include <iostream>
 
template<class T>
void test_forward(T&&) {
    // T&& 형식을 출력해 보자 (C++ 타입 트레잇 + 문자열)
    if      (std::is_lvalue_reference<T&&>::value) std::cout<<"T&& is lvalue reference\n";
    else if (std::is_rvalue_reference<T&&>::value) std::cout<<"T&& is rvalue reference\n";
    else                                           std::cout<<"T&& is not a reference?\n";
}
 
int main(){
    int x = 0;
 
    // 1) T = int
    test_forward<int>(std::move(x)); // T&& → int&& → rvalue reference
 
    // 2) T = int&
    test_forward<int&>(std::move(x)); // T&& → int& && → 참조 합침 → int& → lvalue reference
}
 
----------------------------------------------
 
/* 출력 */
T&& is rvalue reference
T&& is lvalue reference
 
----------------------------------------------

위 예제를 통해서 rvalue reference형식을 의도해서 전달해도 lvalue reference와 함침이 발생하여 의도치 않은 동작을 발생시킬 수 있게된다.

위 예제를 주의깊게 보면 금방 이해할 것이라 생각한다.