사실 이런 내용은 ‘템플릿 메타 프로그래밍’ 이라 검색하면 우수수 쏟아진다. 이 개념을 확실히 알아야 Modern C++ 에 한발짝 더 다가갈 수 있다.

Using / Typename

두 가지만 급히 정리

typename 키워드는, 자료형이나 템플릿 인자에 의존하는 타입을 가리키는 한정 명칭 (qualified name) 이 존재할 때 사용합니다. 이 키워드는 템플릿 선언이나 정의 부분에서만 사용합니다. 아래 선언부를 보면,

template<class T> class A
{
  T::x(y);
  typedef char C;
  A::C d;
}

T::x(y) 는 모호합니다. 지역 변수가 아닌 인자 y 를 통해 x() 라는 함수를 호출하는 것인지, 아니면 T::x 타입의 변수 y 를 선언하는 것인지 알 수 없습니다. C++ 컴파일러는 이 구문을 전자, 즉 함수로 인식합니다. 이걸 함수가 아닌 변수 선언으로 인식시키기 위해, typename 을 앞에 입력합니다.

마지막의 A::C d; 도 이상합니다. 클래스 A는 A<T> 를 의미하고 작성했기 때문에, 실제로는 템플릿 인자에 따라 어떤 클래스로 구체화될 지 알 수 없습니다. 구체화에 따라 같은 템플릿 인자를 가질 것이므로, 이건 템플릿 인자에 의존적이라고 볼 수 있습니다. 이 때도 typename 을 앞에 입력합니다.

typename A::C d;

Typedef vs. using

흥미로운 글이다. 링크 둘다 forward declaration 인데, 요약하면 이렇다.

typedef std::shared_ptr<MyClass> MyClassPtr; 
using MyClassPtr = std::shared_ptr<MyClass>;

두 구문은 정확히 같다. 똑같이 작동한다. 하지만 멤버가 정이되는 것 같은 using 이 보기 편하다.

그리고 typedef 는 template 을 지원하지 않는다. vector STL 의 이런 구문이 typedef 로는 지정할 방법이 없다.

using iterator = _Vector_iterator<_Vector_val<_Val_types>>;

Nested Template

생소해서 짧게 정리한다. 방금 본 이 구문은 사실 vector STL 의 _Vector_alloc 클래스의 멤버 함수 시그니처다.

using iterator = _Vector_iterator<_Vector_val<_Val_types>>;

꺽쇠가 중첩되어 있는데, 이게 뭘까. _Vector_iterator 도, _Vector_val 도 모두 템플릿 클래스인 것이다. 그럼 마지막에 _Val_types 는 어디서 온 걸까?

template<class _Alloc_types>
	class _Vector_alloc
	{
public:
	using _Val_types = typename _Alloc_types::_Val_types;

_Vector_alloc 클래스에서 구체화된 클래스 _Alloc_types_Val_types 이다. 이상하다. 그럼 custom class 는 저 멤버 변수가 있어야 vector 를 쓸 수 있나?? 그럴리가..