* 정의

 

decltype(declared type)은 주어진 이름이나 표현식의 형식을 알려주는 역할을 한다. 주로 템플릿 매개변수에 의존하는 타입을 표현하기 어렵거나 불가능한 제네릭 프로그래밍에서 사용된다.

 

#제네릭 프로그래밍(generic programming) : 데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있는 기술에 중점을 두어 재사용성을 높일 수 있는 프로그래밍 방식이다.

 

 

* 동작 방식

 

템플릿과 auto의 형식 연역과 달리 decltype은 주어진 이름이나 표현식의 구체적인 형식을 그대로 알려준다.

함수의 반환 형식이 그 매개변수 형식들에 의존하는 함수 템플릿을 선언할 때 주로 사용된다.

 

 

- decltype 활용 : 함수 반환형식

 

예를 들어 템플릿 컨테이너 클래스의 자료형마다 operator[]을 지원하고 operator[]의 반환 값이 다르다면 다음과 같이 decltype을 활용하여 정의하면 명확하게 표현할 수 있다.

// C++ 11버전
template<typename ContainerType, typename IndexType>
auto AuthAndAccess1_1(ContainerType& c, IndexType i)
-> decltype(c[i])
{
	// authenticateUser();
	return c[i];
}

// C++ 14버전
template<typename ContainerType, typename IndexType>
decltype(auto) AuthAndAccess1_2(ContainerType& c, IndexType i)
{
	// authenticateUser();
	return c[i];
}

// 템플릿 형식 연역을 적용 
// 참조도 포인터도 아닌 경우에 해당한다. operator[]가 참조를 반환해도 참조가 제거된다.
template<typename ContainerType, typename IndexType>
auto AuthAndAccess2(ContainerType& c, IndexType i)
{
	// authenticateUser();
	return c[i];
}


void Decltype_Function(void)
{

	vector<int> container = { 1,2,3,4,5 };
	

	AuthAndAccess1_1(container, 2) = 5;
	AuthAndAccess1_2(container, 2) = 5;
	
	// 반환형이 int 형으로 연역되기 때문에 오른값을 반환한다. 오른값 int에 5를 배정할 수 없다.
	// AuthAndAccess2(container, 2) = 5;
}

단순 auto 키워드를 사용하면 템플릿 형식 연역을 사용하게 되고 그냥 auto형이기 때문에 포인터도 참조도 아닌 경우에 해당하여 operator[]가 참조를 반환하더라도 참조가 제거되어 반환되는 것을 볼 수 있다. 함수 결과가 오른값이며 오른 값에는 다른 값을 배정할 수 없기 때문에 컴파일 에러가 발생한다.

 

반대로 decltype을 활용한 함수들을 보면 operator[]가 반환하는 형식 그대로 다시 돌려주는 것을 확인할 수 있다. std::vector<int>의 operator[]은 int&을 반환하는데, 이를 그대로 다시 반환한다. 즉 함수 결과가 왼값이다.

 

위 함수에서 오른값을 왼값 참조로 넘길 수 없기 때문에 오른값을 전달할 수 없다. 만약 오른값도 받도록 만들기 위해서는 보편 참조를 사용하면 된다.

template<typename ContainerType, typename IndexType>
decltype(auto) AuthAndAccess1_3(ContainerType&& c, IndexType i);

 

 

- decltype(auto)

 

위의 코드에서 C++14 버전의 경우 decltype(auto)를 사용했는데 의미는 다음과 같다.

  • auto는 해당 형식이 연역되어야 함을 뜻하고 decltype은 그 연역 과정에서 decltype 형식 연역 규칙들이 적용되어야 함을 뜻한다.

 

decltype(auto)는 변수 선언시 초기화 표현식에 decltype 형식 연역 규칙들을 적용하고 싶은 경우 유용히 사용될 수 있다.

int x = 3;
const int& crx = x;
decltype(auto) dacrx = crx;	// const int& 형식

 

다만 이 기능은 주의해서 사용해야한다. x가 int형일 때, decltype(x)는 int형이지만 decltype((x))는 int&형이다. 따라서 반환할때 괄호를 잘못 넣으면 예상치 못한 결과가 발생할 수 있다.

// int 형 반환
decltype(auto) f1()
{
	int x = 3;
	return x;
}

// int& 형 반환
decltype(auto) f2()
{
	int x = 3;
	return (x);
}

 

 

- 기타 활용 방법

 

컴파일러의 진단 메시지를 통해 타입 확인을 할 수 있다.

template<typename T>
class TD;

void Decltype_TypeDisplayer()
{
	int x = 3;
	int* px = &x;

	TD<decltype(px)> a;
}

 

'C++' 카테고리의 다른 글

스마트 포인터 - std::unique_ptr  (0) 2022.03.22
스마트 포인터 개요  (0) 2022.03.21
auto의 형식 연역 규칙  (0) 2022.03.15
템플릿의 형식 연역 규칙  (0) 2022.03.11
오른값과 왼값  (0) 2021.11.10

+ Recent posts