본문 바로가기
Object Oriented Programming(C++)/Effective C++

Effective C++ | 항목 42 typename의 두 가지 의미를 제대로 파악하자

by continue96 2024. 8. 6.

Effective C++ 항목 42

 

항목 42 typename의 두 가지 의미를 파악하자

42.1 class vs. typename

42.1.1 템플릿 타입 매개변수

  • 템플릿 매개변수를 선언하는 경우, class와 typename은 완전히 같다.
template<typename T>
class CBase;

template<class T>
class CBase;

 

 42.1.2 중첩된 의존 이름

  • 의존 이름
    • 템플릿 안에 있는 이름 중에 템플릿 매개변수에 의존적인 이름을 의존 이름(dependent name)이라고 한다.
    • 클래스 안에 중첩되어 있는 의존 이름을 중첩된 의존 이름(nested dependent name)이라고 한다.
    • T::iterator, T::const_iterator
  • 비의존 이름
    • 템플릿 매개변수와 관계없는 이름을 비의존 이름(non-dependent name)이라고 한다.
    • int, float
template<typename T>
void Print1st(const T& container)// T는 중첩된 의존 이름이 아니므로 typename을 작성하지 않는다.
{
	if (!container.empty())
	{
		// T::const_iterator는 중첩된 의존 이름이므로 typename을 작성한다.
		typename T::const_iterator iter(container.begin());
	}
}

 

  • 템플릿 안에 중첩된 의존 타입 이름이 있는 경우, 컴파일러는 이 이름이 타입이 아니라고 가정한다.
    • 따라서 중첩된 의존 타입 이름을 타입으로 인식할 수 있도록 typename 키워드를 붙인다.
    • 중첩된 의존 타입 이름이 아닌 경우, typename 키워드를 붙이지 않는다.
    • 단, 중첩된 의존 타입 이름이 부모 클래스의 리스트에 있거나 멤버 초기화 리스트 안에 부모 클래스 식별자로 있는 경우, typename 키워드를 붙이지 않는다.
template<typename T>
class Child : public Parent<T>::Nested// 상속받는 기본 클래스 리스트는 typename을 쓰지 않습니다.
{
public:
	// 멤버 초기화 리스트에 있는 부모 클래스 식별자는 typename을 쓰지 않습니다.
	explicit Child(int x) : Parent<T>::Nested(x)
	{
		typename Base<T>::Nested temp;
	}
};

 

 

 42.1.3 typedef

  • 특정 정보 클래스(trait)에 속한 멤버 이름을 typedef 이름으로 만들 때, 그 멤버 이름과 똑같이 짓는 것이 관례이다.
    • typedef 키워드 다음에 typename 키워드가 나란히 있어도 문제가 없다.
template<typename T>
void WorkWithIter(T iter)
{
	// typedef 키워드, typename 키워드가 연속적으로 나와도 문제 없습니다.
	typedef typename std::iterator_traits<T>::value_type value_type;
	value_type temp(*iter);
}

 

NOTE
① 템플릿 매개변수를 선언할 때, class와 typename은 서로 똑같다.
② 중첩된 의존 타입 이름을 선언할 때는 반드시 typename을 사용한다. 단, 중첩 의존 이름이 부모 클래스 리스트에 있거나 멤버 초기화 리스트 안에 부모 클래스 식별자로 있는 경우는 예외다.

댓글