KoreanFoodie's Study

Effective Modern C++ | 항목 2 : auto 의 형식 연역 규칙을 숙지하라 본문

Tutorials/C++ : Advanced

Effective Modern C++ | 항목 2 : auto 의 형식 연역 규칙을 숙지하라

GoldGiver 2022. 10. 26. 09:48

C++ 프로그래머의 필독서이자 바이블인, 스콧 마이어스의 Modern Effective C++ 를 읽고 기억할 내용을 요약하고 있습니다. 꼭 읽어보시길 추천드립니다!

항목 2 : auto 의 형식 연역 규칙을 숙지하라

핵심 :

1. auto 형식 연역은 대체로 템플릿 형식 연역과 같지만, auto 형식 연역은 중괄호 초기치가 std::initializer_list 를 나타낸다고 가정하는 반면, 템플릿 형식 연역은 그렇지 않다는 차이가 있다.
2. 함수의 반환 형식이나 람다 매개변수에 쓰인 auto 에 대해서는 auto 형식 연역이 아니라 템플릿 형식 연역이 적용된다.


한 가지 기이한 예외를 빼면, auto 형식 연역이 곧 템플릿 형식 연역이다. 그 기이한 한 가지 다른 예외를 보자.

#include <iostream>
#include <typeinfo>

int main()
{
	// x1, x2, x3 는 int
	int x1 = {27};
	int x2{27};
	auto x3{27};

	// x4 의 형식은 std::initializer_list<int>
	auto x4 = {27, 28, 29};
	// 에러! 값들이 다 같은 형식이어야 함
	auto x5 = {1, 2, 3.0};

	std::cout << typeid(x1).name() << std::endl; // i
	std::cout << typeid(x4).name() << std::endl; // St16initializer_listIiE
}

즉, auto 의 경우 중괄호를 이용했을 때 std::initializer_list 가 불린다는 것이 단 한가지의 차이점이다.

중괄호 초기치를 이용한 템플릿 연역 예시를 보자.

template<typename T>
void f(T param);
// 오류! 에 대한 형식 연역 불가

f({1, 2, 3}); 

template<typename T>
void f(std::initializer_list<T> param);

// T 는 int 로, param 은 std::initializer_list<int> 로 연역
f({1, 2, 3});


함수 반환 형식을 auto 로 지정하면 템플릿 형식 연역의 규칙들이 적용된다. 이는 람다 함수의 경우도 마찬가지이다.

auto createInitList()
{
	// 오류! {1, 2, 3} 의 형식 연역 불가
	return {1, 2, 3};
}


int main()
{
	 std::vector<int> v;

	 auto resetV = [&v](const auto& new Value) { v = newValue; };

	 // 오류! {1, 2, 3} 의 형식 연역 불가
	 resetV({1, 2, 3});
}
Comments