본문 바로가기
Effective C++

이펙티브 C++ item 42 : typename의 두 가지 의미를 제대로 파악하자.

by gong재이 2022. 7. 8.
반응형

class 와 typename의 차이점은?

template<class T> class Widget;
template<typename T> class Widget;

 

템플릿의 타입 매개변수를 선언하는 경우 class 와 typename의 의미는 완전히 동일하다.

템플릿 안에서 참조할 수 있는 이름의 종류

template<typename C>
void print2nd(const C& container)
{
    if(container.size() >= 2){
        C::const_iterator iter(container.begin());	// 첫째 원소에 대한 반복자를 얻는다.
        
        ++iter;
        int value = *iter;
        std::cout << value;
    }
}

 

dependent name(의존 이름)

템플릿 매개변수에 종속된 이름을 의미한다.
클래스 안에 중첩되어 있는 경우 중첩 의존 이름(nested dependent name) 이라 한다.

non-dependent name(비의존 이름)

템플릿 매개변수와 상관없는 타입 이름을 말한다.


typename을 반드시 써야 하는 경우

1. 중첩 의존 타입인 경우

template<typename C>
void print2nd(const C& container)
{
    C::const_iterator *x;
    ...
}

 

dependent name의 경우 템플릿 매개변수 C에 따라 모호성이 발생하게 된다.
따라서, C++은 모호성을 해결하기 위해 '템플릿 안에서 중첩 의존 이름(nested dependent type)을 만나게 되면
프로그래머가 타입을 컴파일러에 알려주지 않는 한, nested dependent name은 기본적으로 타입이 아닌 것으로 해석된다.

 

템플릿 매개변수를 이용해 적힌 타입이 컴파일러 입장에서 '타입이다'라고 알려주는 키워드가 typename인 것이다.

template<typename C>
void print2nd(const C& container)
{
    if(container.size() >= 2){
        typename C::const_iterator iter(container.begin());	// 첫째 원소에 대한 반복자를 얻는다.
        ...
    }
}

템플릿 안에서 nested dependent name을 참조하는 경우에는 항상 그 이름 앞에 typename 키워드를 붙여주자.

template<typename C>
void f(const C& container	// typename 쓰면 안됨.
       , typename C::iterator iter);	// typename 꼭 써야 함.

C는 중첩 의존 타입이 아니어서  typename을 붙이면 안된다.
C::iterator는 분명한 중첩 의존이름이기 때문에 typename을 붙인다.

 

2. 예외

중첩 의존 타입 이름이 기본 클래스의 리스트에 있거나(상속) 멤버 초기화 리스트 내의 기본 클래스 식별자로서 있는 경우이다.

template<typename T>
class Derived::public Base<T>::Nested{	// 상속되는 기본 클래스 리스트 : typename 쓰면 X
public:
    explicit Derived(int x)
    : Base<T>::Nested(x)	// 멤버 초기화 리스트에 있는 기본 클래스 식별자 : typename 쓰면 X
    {
        typename Base<T>::Nested temp;	// 중첩 의존 타입이름 : typename O
        ...
    }
    ...
}

 

반응형

댓글