lunchclass / cpp

6 stars 3 forks source link

[Question] Item 24 - Universal Reference 와 Rvalue Reference를 구별하라 #5

Open JayCheck opened 7 years ago

JayCheck commented 7 years ago

Item 24의 내용 중 아래와 같은 내용이 나옵니다.

Even the simple presence of a const qualifier is enough to disqualify a reference from being universal:

template<typename T> 
void f(const T&& param);         // param is an rvalue reference

그런데 이유는 전혀 나오지 않습니다. 저자는 단지 "Universal reference(== forwarding reference) 는 반드시 type deduction 이 있으면서 "T&&" 형태가 아니면 Universal reference 가 안된다" 라고만 설명하고 있습니다. Scott mayers 의 다른 article

StackOverflow 에서도 동일한 의문을 제기하는 글이 있습니다. https://stackoverflow.com/questions/38814939/why-adding-const-makes-the-universal-reference-as-rvalue 답변에 따르면 먼저 표준에는 forwarding reference 의 정의 자체가 "A forwarding reference is an rvalue reference to a cv-unqualified template parameter"로 const 가 없는 Rvalue reference 형태라고 되어 있습니다. 그리고 이렇게 한 이유는 const T&& 도 universal reference 로 허용하게 되면 rvalue 만 받고자 하는 함수 overloading 을 만들 수가 없기 때문이라고 설명하고 있습니다.

The problem is that we would have no way to overload a template function who takes only rvalue reference as parameter if both T && and const T && are allowed to use as forwarding references. – Carousel

romandev commented 7 years ago

시발.. 개장문의 글을 썼는데 브라우저 죽었네...

romandev commented 7 years ago

Universal Reference VS Forwarding Reference

Universal Reference라는 용어는 이 표준에 대한 제안 된 초기에 사용되던 이름이며, 최신 표준에서는 Forwarding Reference로 불리거나 불릴 예정이라고 합니다.

책에서 말하는 Forwarding Reference (a.k.a Universal Reference) [1]

하나의 참조가 보편 참조(Forwarding Reference)이려면 반드시 형식 연역(타입 추론)이 관여해야 한다. 그런데 이는 필요조건일 뿐 충분조건은 아니다. 참조 선언의 형태(form)도 정확해야 하는데, 그 형태는 상당히 제한적이다. 구체적으로 말해서 딱 "T&&"의 형태이어야 한다.

표준에서 말하는 Forwarding Reference [2]

A forwarding reference is an rvalue reference to a cv-unqualified template parameter.

즉, @JayChl님의 설명대로 const(or volatile)이 아닌 template parameter이 rvalue reference를 말합니다. 여기서 다소 혼란을 줄 수 있는 부분이 rvalue reference라는 말인데, 여기서의 rvalue reference란 아마도 rvalue 자체를 의미하는 것이 아니라 && rvalue reference 기호 자체를 의미함에 주의해야 합니다.

표준 제안서(?)에서 말하는 Forwarding Reference [3][4]

To the C++ programmer, a parameter of type C&& is always an rvalue reference—except when C is a template parameter type or auto, in which case it behaves very differently even though language-technically it is still an rvalue reference.

We intentionally overloaded the && syntax with this special case, but we did not give this special case a name. It needs a distinct name so that we can talk about it and teach it. This has already been discovered in the community, thanks to Scott Meyers in particular.

해석해보면, 결국, && (rvalue reference)를 그저 오버로딩(overloading)하여 재사용하였다는 것입니다. 즉, forwarding reference는 rvalue reference(기호가 아닌 의미상)와는 모양만 같을 뿐 전혀 다른 의미로 사용됩니다.

그렇다면 대체 "왜"라는 생각이 들 수 있는데, 추측컨데, 그것은 아마도 C++ 표준 커뮤니티의 특성이 아닌가 생각합니다. 이미 기존에도 이처럼 같은 키워드를 서로 다른 의미로 오버로딩하는 경우를 많이 찾을 수 있습니다. 대표적으로 static키워드가 있습니다. static의 경우 local variable에 사용되면 stack이 아닌 static 영역에 정의되는 효과를 볼 수 있습니다. 한편, global variable에 사용되면 static은 변수의 저장공간이 아닌 파일 scope을 internal link로 제한하는 한정자의 형태로 사용됩니다.

그럼.. 20000

[1] Modern Effective C++ (Item 24) [2] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf [3] https://isocpp.org/files/papers/N4164.pdf [4] https://isocpp.org/blog/2014/10/n4164