// int& => int 타입의 lvalue만 전달할 수 있다.
void f1(int& arg) {}
// int&& => int 타입의 rvalue만 전달할 수 있다.
void f2(int&& arg) {}
// T 자체가 참조(& or &&)를 포함하고 있다면, reference collapsing 규칙을 적용.
// T의 뒤쪽에 & 한 개가 붙어 있으므로 T가 어떤 참조로 와도 lvalue 이다.
template<class T> void f3(T& arg) {}
//
template<class T> void f4(T&& arg) {}
int main()
{
int n = 0;
f1(n); // ok
f1(0); // error
f2(n); // error
f2(3); // ok
f3(n); // ok
f3(0); // error
f4<int>(0); // T=int T&&=int&& f4(int&& arg)
f4<int&>(n); // T=int& T&&=int& && f4(int& arg)
f4<int&&>(3); // T=int&& T&&=int&& && f4(int&& arg)
// forwarding reference, lvalue, rvalue 모두 전달 할 수 있다.
f4(n); // T=int& f4(int& arg)
f4(0); // T=int f4(int&& arg)
}
Universal vs Forwarding
- Effective 책 저자가, 당시에 이름이 없었기 때문에 Universal이라는 이름을 사용했다.
- 이후 표준 위원회 에서는 forwarding reference 라고 명명 했다.
lvalue 와 rvalue 모두 받을 수 있는 함수 만들기
void foo(int arg) {}
void foo(const int& arg) {}
void foo(int& arg) {}
void foo(int&& arg) {}
template<class T> void foo(T&& arg) {}