본문 바로가기
책 정리/Effective C++ 3rd

항목 42. typename의 두 가지 의미를 제대로 파악하자

by ocean20 2020. 3. 17.

1. class와 typename 공통점

템플릿 매개변수 선언시 class typename 완전히 동일하다.

template<class T> class Widget;   // class 사용
template<typename T> class Widget;   /typename 사용

 

 

2. class와 typename 차이점

하지만 class typename 키워드가 다르게 사용되는 경우가 있다.

template<typename C> 
void print2nd(const C& container)  //컨테이너에 들어 있는 2번째 원소를 출력합니다.
{
  if (container.size() >= 2 ) {
    C::const_iterator iter(container.begin()); //첫째 원소에 대한 반복자를 얻습니다.

    ++iter;  // 두번째원소로 iter를 옮깁니다.
    int value = *iter;  // value에 값을 복사합니다.
    std::cout << value;  // value을 출력합니다.
  }
}

* 풀이

  1) 템플릿 내의 이름 중(C::const_iterator iter)에 위와같이 템플릿 매개변수에 종속된 가리켜 의존 이름(dependent name)이라고 한다. 클래스 안에 중첩되어 있는 경우가 있는데, 경우의 이름은 중첩 의존 이름(nested dependent name)이라고 부른다

 

  2) 또다른 지역변수, value 템플릿 매개변수와 상관없는 타임이름이므로, 비의존 이름(non-dependent)이라고 한다.

 

 

3) 중첩 의존 이름의 올바른 사용방법

  - 중첩 의존이 코드안에 있을때 에러를 꽃피울 수 있다.

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

*풀이 : 우리는 C::const_iterator 대한 포인터인 지역변수로서 x 선언하고 있는 것으로 생각하겠지만, 만약 C const_iterator라는 정적데이터멤버를 갖고 있고, x 전역변수라면, 컴파일러는 데이터를 곱셈연산한다고 생각할 것이다.

따라서, 바로 이경우에 C::const_iterator 앞에 typename이라는 키워드 명시해준다. (데이터가 아니고, 타입이라는 걸 명시하기위해)

 

 

4. typename 예외

- "typename 중첩의존이름앞에 꼭 붙여주여야 한다"라는 규칙에 예외가 2가지 있다.

  1) 상속되는 기본클래스의 리스트에 있을때

  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
    …
  }
  …
};

이것만은 알아두자

- 템플릿 매개변수를 선언할 , class typename 서로 바꾸어 써도 무방합니다.

- 중첩의존타입이름을 식별하는 용도에는 반드시 typename 사용해야한다. , 중첩의존이름이 기본클래스 리스트 or 멤버 초기화 리스트내에 기본 클래스 식별자로 있을 경우는 예외이다.

댓글