템플릿 매개변수를 선언하는 경우의 class 및 typename은 같은 의미 지닌다.
template<class T> class Widget;
template<typename T> class Widget;
다음 코드에서 C::const_iterator처럼 매개변수인 C에 의존적인 것들을 의존 이름(dependent name)이라고 합니다. 그리고 의존 이름이 어떤 클래스 안에 중첩되어 있는 경우에는 중첩 의존 이름(nested dependent name)이라고 부릅니다.
template<typename C>
void print2nd(const C& container)
{
if (container.size() >= 2)
{
C::const_iterator iter(container.begin());
int value = *iter; std::cout << value;
}
}
구문 분석기는 템플릿 안에 중첩 의존 이름을 만나면 타입이라고 알려 주지 않는 한 그 이름이 타입이 아니라고 가정한다. 그래서 다음 코드에서 C::const_iterator
는 타입이 아니라고 해석된다.
template<typename C> void print2nd(const C& container)
{
if (container.size() >= 2)
{
C::const_iterator iter(container.begin());
...
이를 해결하기 위해여 typename 키워드를 이용해서 typename C::const_iterator
로 고친다면, C::const_iterator
는 타입이 됩니다.
template<typename C> void print2nd(const C& container)
{
if (container.size() >= 2)
{
typename C::const_iterator iter(container.begin());
...
template<typename IterT> void workWithIterator(IterT iter)
{
typedef typename std::iterator_traits<IterT>::value_type value_type;
value_type temp(*iter);
...
}
이처럼 typename키워드는 중첩 의존 이름을 식별하는 용도에 써야합니다.
하지만 이러한 규칙에도 예외는 존재합니다.
다음과 같이 기본 클래스의 리스트에 있거나 초기화 리스트 내의 기본 클래스의 식별자로서 있을 경우 typename을 붙여주면 안 된다.
template<typename T> class Derived : public Base<T>::Nested
// base class list: typename not allowed
{
public:
Derived(int x) : Base<T>::Nested(x)
{
typename Base<T>::Nested temp; ...
} ...
};