더북(TheBook)

elements에 메모리를 할당하다가 예외가 발생할 수 있으므로 생성자는 try 블록 함수여야 한다. 이렇게 하면 예외가 발생했을 때 예외를 잡아서 응답할 수 있지만, 예외는 재전송되어야 한다. 즉, catch 블록에서 예외를 재전송(rethrow)하지 않더라도 예외는 어쨌든 재전송된다. 템플릿 타입 매개변수는 함수 템플릿 정의가 클래스 템플릿에 묶여 있으므로 템플릿 타입 매개변수는 생성자 이름을 한정(qualification)할 때 반드시 쓰인다. 멤버 이름을 위한 한정자에는 typename 키워드를 사용해서는 안 된다. typename은 템플릿 매개변수 목록에만 쓰여야 한다.

물론, 클래스 템플릿의 멤버 함수를 위해 외부 템플릿을 inline으로 지정할 수 있다. 예를 들어 Array 템플릿의 복제 생성자를 inline으로 정의한 코드를 생각해보자.

template <typename T>
inline Array<T>::Array(const Array& other)
try : elements {new T[array.count]}, count {array.count}
{
  for (size_t i {}; i < count; ++i)
    elements[i] = array.elements[i];
}
catch (std::bad_alloc&)
{
  std::cerr << "Array 객체 복제를 위한 메모리 할당에 실패했습니다." << std:: endl;
}

이 코드는 할당 연산자가 타입 T에 대해 동작한다고 가정하고 있다. 템플릿 코드를 보지 않으면 이 코드를 사용할 때까지 할당 연산자에 종속 관계가 있다는 사실을 깨닫지 못할 것이다. 앞에서 설명한 것처럼 이 코드는 메모리를 동적으로 할당하는 클래스에 항상 할당 연산자와 나머지 네 가지 멤버를 정의하는 게 얼마나 중요한지 보여준다.

Note ≣

class와 typename 키워드는 템플릿 매개변수를 지정할 때 서로 바꿔 쓸 수 있으므로 템플릿을 정의할 때 template<typename T>template<class T> 어느 쪽이든 쓸 수 있다. T가 반드시 클래스 타입을 의미하는 것도 아니고 템플릿 타입 인수는 기본 타입과 클래스 타입 둘 다 될 수 있어서 표현력이 더 좋다고 생각하므로 나는 typename을 사용하는 쪽을 더 좋아한다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.