auto와 decltype, 목적이 다른 두 키워드
auto와 decltype은 서로 다른 용도로 설계되었기 때문에 일대일로 대응되지 않습니다. auto는 C++11부터 도입된 키워드로, 변수의 타입을 자동으로 추론하는 데 사용됩니다. 반면 decltype은 타입 지정자(type specifier)로서, 주어진 표현식의 타입을 그대로 산출합니다.
auto가 변수에 대입되는 값을 기반으로 타입을 추론하는 것과 달리, decltype은 전달받은 표현식 자체에서 타입을 도출하며, 그 결과 타입을 다른 변수 선언에 바로 활용할 수 있습니다.
auto의 타입 추론 규칙
auto는 템플릿 매개변수 추론(template argument deduction)과 동일한 규칙을 따릅니다. 자세한 내용은 cppreference의 템플릿 인자 추론 문서에서 확인할 수 있습니다.
decltype의 타입 결정 규칙
decltype 역시 C++ 표준에 명시된 규칙을 따라야 합니다. sizeof 연산자와 마찬가지로 decltype의 피연산자는 실제로 평가되지 않으며(unevaluated), decltype(e)가 반환하는 타입은 아래와 같이 결정됩니다.
- 표현식 e가 지역 범위나 네임스페이스 범위의 변수, 정적 멤버 변수 또는 함수 매개변수를 가리키는 경우 → 해당 변수나 매개변수의 선언된 타입
- e가 함수 호출이거나 오버로드된 연산자 호출인 경우 → 해당 함수의 선언된 반환 타입
- 그 외의 경우 → e가 lvalue이면
T&(T는 e의 타입), rvalue이면T
이러한 의미론은 제네릭 라이브러리 작성자의 요구를 충족시키면서도, 초보 프로그래머에게 직관적으로 다가가도록 설계되었습니다. decltype의 반환 타입은 소스 코드에 선언된 객체나 함수의 타입과 항상 정확히 일치하기 때문입니다. 좀 더 공식적으로 살펴보면, 첫 번째 규칙은 괄호로 묶이지 않은 id-expression과 클래스 멤버 접근 표현식에 적용되며, 함수 호출의 경우에는 오버로드 해결(overload resolution) 규칙에 따라 정적으로 선택된 함수의 반환 타입이 추론됩니다.
예제 코드
auto와 decltype을 활용한 타입 추론 예제입니다.
#include <iostream>
#include <vector>
using namespace std;
int main() {
// auto를 사용한 타입 추론
vector<int> arr(10);
for (auto it = arr.begin(); it != arr.end(); ++it) {
cin >> *it;
}
// decltype을 사용한 타입 추론
for (decltype(arr.begin()) it = arr.begin(); it != arr.end(); ++it) {
cin >> *it;
}
return 0;
}auto와 decltype의 미묘한 차이
주목할 점은 decltype이 나타내는 타입이 auto가 추론하는 타입과 다를 수 있다는 것입니다. 이러한 미묘한 차이를 더 깊이 이해하고 싶다면 Thomas Becker의 "auto and decltype" 시리즈(thbecker.net)를 참고해 보세요. 12페이지 분량의 이 글은 C++ 타입 추론의 세부적인 동작 방식을 체계적으로 설명하고 있어, 두 키워드의 차이를 확실히 구분하는 데 큰 도움이 됩니다.