C++에서 Auto 타입이 어떻게 추론되는지 알아보자.
1. Auto
Auto 는 변수 초기화시에 자동으로 타입이 추론 되는 타입이다. 예를 들어 아래와 같은 코드는 변수 i를 int 타입으로 추론한다.
auto i = 10;
C++ 11 버전 이전에는 auto가 지역변수를 의미할 뿐이므로 주의해야 한다.
2. Auto 타입 추론
기본적으로 두가지 예외를 제외하고 아래 포스팅의 템플릿 타입 추론과 동일하게 추론된다.
Item 1. 템플릿 타입 추론
C++ 템플릿이 타입을 어떻게 추론하는지 그 법칙을 알아보자. 1. 템플릿 일단, 템플릿이 뭐지? 라는 분을 위해 간략히 설명 하자면, 템플릿은 Generic 프로그래밍을 위해 C++ 이 제공하는 장치로, 변
drogrammer.tistory.com
2.1. 레퍼런스의 경우 (auto&)
기본적으로 타입의 레퍼런스로 추론된다. 단, 초기화용으로 주어진 변수가 레퍼런스일 경우 레퍼런스를 한번 더 붙이지 않는다.
int i = 1;
int& ir = i;
auto& ai = i; // int& 로 추론
auto& air = ir; // int& 로 추론
const auto& cai = i; // int const& 로 추론
const auto& cair = ir; // int const& 로 추론
2.2. 포인터의 경우 (auto*)
int i = 1;
const int* pi = &i;
auto* api = &i; // int* 로 추론
auto* acpi = pi; // int const* 로 추론
2.3. Universal 레퍼런스의 경우 (auto&&)
- 초기화 변수가, lvalue 면 2.1. 과 동일하게 추론한다.
- 초기화 변수가, 식, 리터럴 등의 rvalue 면 unversal 레퍼런스로 추론한다.
int i = 1;
int& ir = i;
const int ci = 1;
const int& cir = ci;
auto&& uai = i; // int& 로 추론 (lvalue)
auto&& uair = ir; // int& 로 추론 (lvalue)
auto&& uaci = ci; // int const& 로 추론 (lvalue)
auto&& uacir = cir; // int const& 로 추론 (lvalue)
auto&& ual = 10; // int&& 로 추론 (rvalue)
auto&& uaf = i + ir; // int&& 로 추론 (ravlue)
2.4. 파라미터 타입이 value 타입일 경우
초기화 변수의 레퍼런스, 상수(const), volatile 특성은 제거하고 추론한다.
int i = 1;
int& ir = i;
const int ci = 1;
const int& cir = ci;
auto ai = i; // int 로 추론 (lvalue)
auto air = ir; // int 로 추론 (lvalue)
auto aci = ci; // int 로 추론 (lvalue)
auto acir = cir; // int 로 추론 (lvalue)
auto al = 10; // int 로 추론 (rvalue)
auto af = i + ir; // int 로 추론 (rvalue)
2.5. 그 외 특이한 케이스
2.5.1. 배열 (array) 추론
초기화 변수가 배열인 경우에는 value 추론 (auto) 과 레퍼런스 추론 (auto&) 결과가 다르다. Value 추론은 배열을 포인터로 추론해 내지만, 레퍼런스로 추론하면 고정크기 배열의 레퍼런스로 추론해 낸다.
int ia[] = {1, 2, 3, 4, 5, 6};
auto aia = ia; // int* 로 추론
auto& aiar = ia; // int [6]& 로 추론
2.5.2. 함수 포인터의 경우
초기화 변수가 함수일 경우에는 2.5.1. 배열 추론과 유사하게 value 추론 (auto) 과 레퍼런스 추론 (auto&) 결과가 다르다. Value 추론은 함수 포인터로 추론해 내지만, 레퍼런스 추론은 함수 레퍼런스로 추론해 낸다.
// 추론 대상 함수
void func(int, double) {}
auto afunc = func; // void (*)(int, double) 로 추론
auto& afuncr = func; // void (int, double)& 로 추론
2.6. 예외
템플릿 추론과 방식이 다른 예외 케이스를 확인해보자.
2.6.1. 초기화 리스트 : 중괄호 초기화
중괄호를 이용하여 리스트 형태의 초기화를 할경우 std::intializer_list<T> 타입으로 추론된다.
auto ail = {10, 20, 30}; // std::initializer_list<int>
초기화 리스트에 동일한 타입의 값을 넣지 않으면 컴파일 에러가 발생한다.
auto aile = {10, 20, 30.0}; // error. can not deduce 'auto' type
참고로 템플릿 타입 추론은 초기화 리스트를 지원하지 않는다.
2.6.2. 함수 리턴 값, 람다 파라미터 타입
auto를 함수의 리턴 값 및 람다 파라미터 타입으로 사용할 경우 템플릿 추론 방식이 사용된다. 예를 들어, 2.6.1. 초기화 리스트가 지원되지 않는다.
auto aFunc() { return {10, 20, 30}; } // error
auto aLambda = [](const auto& value) {};
aLambda({10, 20, 30}); // error
댓글