Outdated/Core Language

[C++ Core] 타입 추론(type deduction) - auto와 decltype

해달 2018. 8. 13. 17:31

[C++ Core] 타입 추론(type deduction) - auto decltype

타입 추론 : auto 그리고 decltype()

C++11부터 C++은 구문으로부터 타입을 추론할 수 있다. 바로 auto decltype()이다. 이 메커니즘이 제공됨으로써 더욱 간결하고 효율적인 코드 작성이 가능해졌다. 두 메커니즘이 추론하는 타입은 모두 컴파일러가 이미 알고있는 구문의 타입만을 보고한다.

auto 타입 지정자

변수를 초기화할 때, 명시적 타입을 적는 대신 auto 타입 지정자를 넣을 수 있다. auto는 그것의 초기자로부터 개체의 타입을 추론하게 되는데, 타입은 변수, const constexpr일 수 있다. 하지만 구문의 타입은 레퍼런스가 될 수 없다. 왜냐하면 레퍼런스는 암시적으로 구문에서 참조되지 않기 때문이다.

다시 말해, auto는 초기자의 타입을 위한 플레이스홀더(placeholder)가 된다.

char c1 = 'c';
int i1 = 10;
auto i2 = 20; // i2는 int이다.

auto는 적기 어렵거나 알기 어려운 타입 대신 사용할 때 유용하다. 또, 코드가 변경되어도 유연하다.

template <typename T>
void foo(std::vector<T>& v)
{
	for (std::vector<T>::iterator iter = v.begin(); iter != v.end(); ++iter)
	{
		// do something
	}

	// 아래 구문이 좀 더 쓰기 편하고 유연하다.
	for (auto iter = v.begin(); iter != v.end(); ++iter)
	{
		// do something
	}
}

// 만일 벡터가 아니라 리스트라면?
template <typename T>
void foo(std::list<T>& v)
{
	// 아래는 재작성 해야 한다.
	for (std::list<T>::iterator iter = v.begin(); iter != v.end(); ++iter)
	{
		// do something
	}

	// 이것은 변경될 필요가 없다.
	for (auto iter = v.begin(); iter != v.end(); ++iter)
	{
		// do something
	}
}

auto 사용시 유의할 점이 하나 있는데, 바로 유니폼 초기자로 초기화하면 예상한 대로 동작하지 않는다는 것이다. 다음의 예를 보자.

auto var1{ 10 }; // std::initializer_list<int>
auto var2 = 10; // int

auto에는 {}-리스트를 의미하는 것이 아니라면, = 연산자를 쓰는 것이 좋다.

작은 유효범위 안에서는 auto를 적극 사용하자. 반대로, 유효범위가 크다면 명시적으로 타입을 적어주는 것이 좋은데, 왜냐하면 오류를 찾을 때 쉽기 때문이다. auto를 사용하면 타입 오류를 확인하는 것이 늦어진다.

decltype() 지정자

decltype()은 함수의 반환형이나 클래스 멤버의 타입 같이 간단하지 않은 초기자의 타입을 추론한다. decltype(expr) expr의 선언된 타입으로, 일반화 프로그래밍에 유용하다.

template <typename T, typename U>
auto operator+(const Matrix<T>& lhs, const Matrix<U>& rhs) -> Matrix<decltype(T{} + U{})>
{
	Matrix<decltype(T{} + U{})> result;
	// omitted
}