안녕하세요, static입니다. C++11에 타입 추론을 위한 키워드들이 추가되었는데요(사실 auto는 키워드 재활용이긴 하지만요.). 코드 가독성을 더 높여주고 복잡한 타입을 생략해서 쓸 수 있게 해주는 아주 고마운 기능이지만, 몇가지 함정이 숨어 있습니다. 어제 알게된 사실인데 한번 글로 정리해보려고 합니다.
우선 auto
는 prvalue로서의 타입을 얻고자 할 때 사용합니다. prvalue는 우리가 흔히 rvalue라고 알고 있는 것들입니다.
int i = 5;
int& ir = i;
auto a = i; // int
auto b = ir; // int
a
, b
의 타입은 둘 다 int
입니다. ir
의 타입이 int&
이긴 하나, prvalue로서의 타입을 추론하기 때문에 b
역시 int가 됩니다.
decltype
은 특정 식의 타입을 얻고자 할 때 사용합니다.
decltype(5) i = 5; // int
decltype(i + 5) j = 5; // int
decltype(j + 5.) k = 5.; // double
i
, j
의 타입은 int
이며 k
의 타입은 double
입니다. i
가 int
인 이유는 5
는 정수 리터럴이기 때문에 int
형이기 때문이며, j
가 int
인 이유는 int + int = int
이기 때문이며, k
가 double
인 이유는 int + double = double
이기 때문입니다.
그러나 decltype
은 알고자 하는 타입의 식과 초기화 할 식 이렇게 2가지의 식을 적어주어야 하는 불편함이 있습니다. 위 예제에서 k
의 경우 j + 5.
와 5.
라는 2개의 식을 사용했는데요. 이런 간단한 코드라면 몰라도 템플릿 들어가고, 규모 커지고 그러면 난리가 날 것입니다. 그래서 decltype(auto)
를 사용합니다.
decltype(auto) i = 5; // int
auto& ir = i; // int&
decltype(auto) ir2 = ir; // int&
i
의 타입은 int
이며 ir
과 ir2
의 타입은 int&
입니다. i
가 int
인 이유는 5
가 int
형이기 때문이며, ir
이 int&
인 이유는 auto
에 의해 int
로 타입이 추론되었으나 &가 붙어 있기 때문에 레퍼런스로 취급되었기 때문입니다. 그리고 ir2
가 int&
인 이유는 ir
의 타입이 int&
이기 때문입니다. 이것이 auto
와 decltype(auto)
의 차이점입니다. auto
는 prvalue로서의 타입을 추론하나, decltype(auto)
는 있는 그대로의 타입을 추론합니다.1
int i = 5;
decltype(i) j = 5; // int
decltype((i)) k = j; // int&
이건 decltype
의 다소 난해한 점이라고 볼 수도 있는데, 설명을 드리겠습니다. 일단 j는 int
형이며 k는 int&
형인데, 식에 괄호가 붙었다고 참조가 된다니 의아하실 수도 있을 것입니다. 그러나 C++의 매력은 난해한 듯 하면서도 정갈한 것 아니겠습니까? j
와 k
는 같은 규칙에 의해 타입이 추론된 것입니다. decltype(i)
는 i
의 타입을 나타냅니다. i
는 int
로 선언되었으므로 int
로 추론되게 됩니다. 같은 원리로, decltype((i))
는 (i)
의 타입을 나타내는데요. 이 값은 lvalue이기 때문에 int&
로 추론됩니다. 그러니까, 전자는 ‘변수’ i
자체의 타입을, 후자는 ‘식’ i
의 타입으로 추론한 것입니다. 그렇다고 decltype((5))
가 int&&
가 되거나 그러지는 않습니다.
마지막으로, auto
는 universal reference를 나타낼 때 쓰일 수도 있습니다. universal reference에 대한 자세한 설명은 이 글에서는 하지 않겠습니다.
int i = 0;
auto&& j = i; // int&
auto&& k = 5; // int&&
auto
에 레퍼런스를 하나만 붙이면 단순히 lvalue reference이지만 두개를 붙이면 rvalue reference가 아닌 universal reference가 됨에 유의해야 합니다.
그럼 글을 마치겠습니다. 감사합니다.
-
decltype(auto)
뿐만이 아니라 모든decltype
이 그렇습니다. ↩