[ Effective C++ ] 정리 모음집
" C++ 프로그래머의 필독서, 스콧 마이어스의 Effective C++ 를 읽고 내용 요약 / 정리 "
" 템플릿 사용 시 typename을 사용해야 하는 경우를 정확히 인지하고 사용하자! "
- 템플릿 매개변수를 선언할 때, class 및 typename은 서로 바꾸어 써도 무방하다!
- 중첩 의존 타입 이름을 식별하는 용도에는 반드시 typename을 사용하자! 단, 중첩 의존 이름이 기본 클래스 리스트에 있거나 멤버 초기화 리스트 내의 기본 클래스 식별자로 있는 경우에는 예외!
template<class T> class Widget;
template<typename T> class Widget;
[ 템플릿 선언문에서 class와 typename을 사용 하는 프로그래머들 ]
- class가 typename보다 타이핑 수가 줄어들어 class만을 사용 하는 프로그래머들도 있다
- 매개변수가 class일 필요가 없다고 외치는듯한 모습에 typename을 선호하는 프로그래머들도 있다
- 어떠한 타입도 허용되는 부분에는 typename을, 사용자 정의 타입만 쓰이는 부분에는 class를 쓰는 프로그래머들도 있다
"마음대로 쓰자!"
template<typename C>
void print2nd(const C& container)
{
if(container.size() >= 2)
{
C::const_iterator iter(container.begin());
++iter;
int value = *iter;
cout << value;
}
}
C::const iterator
📢 의존 이름이 클래스 안에 중첩되어 있는 경우가 있는데 이를 중첩 의존 타입 이름 이라고 한다!
int value;
template<typename C>
void print2nd(const C& container)
{
C::const_iterator* x;
...
}
C::const_iterator
가 타입이 아니라면?- 우연히
const_iterator
라는 이름을 가진 정적 데이터 멤버가C
에 들어있었다면?x
가 다른 전역 변수의 이름이라면?📢 " C::const_iterator와 x를 피연산자로 한 곱셈 연산이 수행 될 수 있다!! "
const_iterator * x
- C++은 모호성을 해결하기 위해 구문 분석기가 템플릿 안에서 중첩 의존 타입 이름을 만나면 그 이름이 타입이 아니라고 가정하는 규칙을 사용 함
template<typename C>
void print2nd(const C& container)
{
if(container.size() >= 2)
{
typename C::const_iterator iter(container.begin());
...
}
}
template<typename C> // typename 사용 가능(선언부 이므로 class와 같은 의미)
void f(const C& contanier, // typename 쓰면 안 됨
typename C::iterator iter); // typename 필수 사용
const C& container
는 의존 이름이지 중첩 의존 타입 이름이 아니다! 📢 typename은 중첩 의존 타입 이름 앞에 붙여 주어야 한다는 규칙에 예외 사항
template<typename T>
class Derived : public Base<T>::Nested // typename 쓰면 안 됨(상속되는 기본 클래스 리스트)
{
public:
explicit Derived(int x)
: Base<T>::Nested(x) // typename 쓰면 안 됨(초기화 리스트 내 기본 클래스 식별자)
{
typename Base<T>::Nested temp; // typename 필수 사용(중첩 의존 타입 이름)
...
}
...
};
template<typename IterT>
void workWithIterator(IterT iter)
{
typedef typename std::iterater_traits<IterT>::value_type value_type;
value_type temp(*iter);
...
}