Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++ auto와 decltype의 차이점과 타입 추론 규칙 완벽 정리

auto와 decltype, 목적이 다른 두 키워드

autodecltype은 서로 다른 용도로 설계되었기 때문에 일대일로 대응되지 않습니다. 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++ 타입 추론의 세부적인 동작 방식을 체계적으로 설명하고 있어, 두 키워드의 차이를 확실히 구분하는 데 큰 도움이 됩니다.