[Modern Effective C++] 2. auto의 타입 추론 규칙을 숙지

Updated:

auto 추론 방식

auto의 타입추론은 [1. 템플릿 타입 추론 규칙을 숙지]에서와 같이 템플릿 타입 추론과 거의 같다.

template <typename T>
void f(ParamType param);

auto에서 타입 추론이 이뤄질 때, auto는 템플릿의 T와 동일한 역할을 하며, 변수의 형식 지정자(type specifier)는 ParamType과 동일한 역할을 한다.

auto x = 27;
const auto cx = x;
const auto& rx = x;

template <typename T>
void func_for_x(T param);           // x의 타입 추론을 위한 개념적인 템플릿

func_for_x(27);

template <typename T>
void func_for_cx(const T param);    // cx의 타입 추론을 위한 개념적인 템플릿

func_for_cx(x);

template <typename T>
void func_for_rx(const T& param);   // rx의 타입 추론을 위한 개념적인 템플릿

func_for_rx(x);

템플릿 타입 추론과 마찬가지로 auto의 타입 추론 또한 변수의 형식 지정자에 따라 세가지 경우로 나뉜다.

  • ParamType이 포인터 또는 참조 형식이지만 Universal Reference는 아닌 경우
  • ParamType이 Universal Reference인 경우
  • ParamType이 포인터도 아니고 참조도 아닌 경우
auto x = 27;              // 경우 3
const auto cx = x;        // 경우 3
const auto& rx = x;       // 경우 1

//경우 2
auto&& uref1 = x;         // x는 int이고 왼값, uref1의 타입은 int&
auto&& uref2 = cx;        // cx는 const int이고 왼값, uref1의 타입은 const int&
auto&& uref3 = 27;        // 27은 int이고 오른값, uref3은 int&&

배열과 함수 이름이 포인터로 붕괴는 방식은 auto 또한 동일하다.

템플릿 타입 추론과 차이점

auto x1 = 27;         // 타입은 int, 값은 27
auto x2(27);          // 위와 동일
auto x3 = { 27 };     // 형식은 std::initializer_list<int>, 값은 { 27 }
auto x4{ 27 };        // 타입은 int, 값은 27

auto는 = 다음에 오는 변수의 초기치가 중괄호 쌍으로 감싸인 형태로 오면 타입 추론은 std::initializer_list로 한다.
그러나 템플릿 함수 인자에 중괄호 초기치를 전달하면 타입 추론이 실패해서 컴파일이 되지않는다.

auto x = { 11, 23, 9 };     // x의 형식은 std::initializer_list<int>

template<typename T>
void f(T param);
f({ 11, 23, 9});            // 오류 T에 대한 타입 추론을 할 수 없음

template<typename T>
void f(std::initializer_list<T> initList);
f({ 11, 23, 9});            // 이건 가능, T는 int로 추론되며, initList는 std::initializer_list<int>로 추론

C++14에서는 함수의 반환 형식을 auto로 지정해서 추론하게 할 수 있으며, 람다의 매개변수에도 auto를 사용이 가능하다.
그러나 이러한 용법은 템플릿 타입 추론이 적용되서 중괄호 초기치를 반환하는 함수는 텀파일이 실패한다.

auto createInitList()
{
  return { 1, 2, 3 };        // 오류 {1,2,3} 타입 추론할 수 없음
}

std::vector<int> v;

auto resetV = [&v](const auto& newValue) { v = newValue; };   // C++14

resetV({1,2,3});             // 오류 {1,2,3} 타입 추론할 수 없음

결론

  • auto 타입 추론은 대체로 템플릿 타입 추론과 같지만, 중괄호 초기치에선 다르다.
  • 함수의 반환 형식이나 람다 매개변수에 쓰인 auto는 템플릿 타입 추론이 적용된다.