<개요> 이번엔 c+11 에서 생긴 decltype에 대해 소개합니다. decltype전에 auto를 모르시는분은 auto를 보고 오시는게 좋을 것 같습니다. |
<decltype> decltype 은 C++11 에서 추가된 키워드로서 auto가 값에 맞는 타입을 추론해준다면, decltype은 값에 맞는 타입을 추출해낸다고 보시면 될 것 같습니다.
1. decltype(x) 는 x가 지역변수 이므로 int 형입니다. 2. decltype((x)) 는 x가 지역변수이고, 내부 괄호를 사용하여 참조로 판단합니다. int& 형입니다. 3. decltype(fx())는 fx()가 const int&& 형이기때문에 const int&& 형으로 판단합니다. 4. decltype(cc.a)는 c클래스 내의 멤버 변수 a 이기때문에 float 형입니다. 5. decltype((ccc.a)) 는 ccc.a 가 float 형이나, 내부 괄호로 감싸졌기때문에 이는 멤버 엑세스가 아닌 식으로 평가됩니다. 그러므로 const float& 형입니다. 추가점) decltype(1) 은 int&& 형입니다, decltype(ccc.a) 라면 이는 const 형이지만 멤버 엑세스이므로 float 형입니다. 사실 변수에서는 decltype 보단 auto 사용을 권고하고 있습니다. 하지만 템플릿같이 컴파일 시간내에 타입을 추론해야하는 경우엔, decltype을 사용해야 합니다. 예를 들어 자기가 글자를 더해야 하거나, 값을 더해야 하거나 하는 경우를 위해 plus 라는 템플릿 변수를 하나 선언합니다.
이 경우엔 대체 어떤 반환타입이 들어가야할까요? C++11 과 C++14 이후에 대해 설명합니다. <C++11 decltype> C++11에선 auto 타입 반환이 가능해지고, 후행 반환 형식 (trailing return type) 으로 decltype 을 사용하고 있습니다.
C++11 에선 single statement lambda (위의 decltype 처럼 단일의 람다) 의 리턴 타입만 추론이 가능하게 됩니다. auto 반환 함수는 반드시 후행 반환 형식을 지정해 주어야 하며, 컴파일 단계에서 인자들을 가지고 타입을 추론해야 하므로 auto만 사용할 시 오류가 발생합니다. 또한 위의 템플릿 함수는 두 값을 묶어 새로운 생성자로 전달 하고 있습니다. 위와 같은 상황에선 후행 반환 형식이 꼭 리턴 형식과 동일 해야 합니다. 그렇지 않으면 rvalue가 들어왔을때 lvalue로 타입을 추론할 수도 있기 때문입니다. <C++14 decltype> C++14 에선 모든 람다와 모든 함수 에서 리턴 타입을 추론할 수 있게됐으며 decltype 의 후행 반환 형식이 삭제되었습니다. (삭제는 아니고... 안써도 됨..)
위는 auto가 자동으로 리턴 타입을 결정해줍니다. 하지만 좋지 않은 방식입니다. 왜냐면 auto는 다른 키워드나 타입이 붙지 않을 시 복사본이 된다는 점입니다.
c 클래스에서는 10개의 배열을 초기화해 []오버로딩으로 값을 읽고 쓰게 해줬습니다. 그러나 c[index]의 반환형은 int& 인것에 비해, auto 키워드 자체만으론 복사본을 리턴하기 때문에 저 3번째 배열은 영영 변하지 않을것입니다. 하지만 decltype을 사용해 준다면 변경 가능합니다.
이렇게 리턴타입을 decltype(auto)로하면, auto의 복사본을 반환형으로 하는게 아닌, c[index]를 가지고 반환 추론을 하기 때문에 int& 형으로 반환됩니다. 또한 T가 rvalue (임시객체) 로 들어올 가능성도 있기때문에 꼭 universal reference로 받아주셔야 합니다.
아악 decltype은 다 이해 했는데 아직도 rvalue lvalue가 절 괴롭히고 있습니다. 도움받은 링크 : https://docs.microsoft.com/ko-kr/cpp/cpp/decltype-cpp?view=vs-2017 |
'C++ > Modern' 카테고리의 다른 글
C++11) explicit, delete, default, override (0) | 2019.02.06 |
---|---|
C++11) constexpr 키워드와 강한 열거형 (0) | 2019.02.05 |
C++11) 람다식 (Lambda Expression) 과 std::function (4) | 2019.02.02 |
C++11) std::forward (perfect forwarding) (4) | 2019.02.02 |
c++11) std::move (move semantics) (2) | 2019.02.01 |