c++ 마지막 과제 동료평가를 했다. seongyle 님을 평가했다. stl 을 다뤄보는 과제이고 그 중, stack 에 iterator 를 추가해서 반복자를 가진 stack 을 만들어보는 과제가 있었다. stack 은 후입 선출을 하는 컨테이너로 iterator 를 따로 갖지 않는다. 아무튼 이 과제에서는 typename
이라는 키워드를 사용한다. 다음과 같이 말이다.
typedef typename ~
typedef 는 키워드를 재정의하기 위해 사용한다. 예를 들어typedef int A
라는 코드는 int 를 A 로 바꿔서 사용하겠다는 의미이다.
아래 그림은 자료형 A 를 B 로 바꾸겠다는 의미이다. std::stack<T>::container_type::const_iterator
라는 긴 이름의 자료형을 const_iterator
로 바꿔쓰겠다는 의미이다.
그렇다면 typename 은 도대체 뭘까??
나는 처음에 컴파일러가 typedef 할 대상이 변수인지 자료형인지 구분하기 위해 사용하는 줄 알았다. 평가를 진행하며 seongyle 님한테 typedef 사용하는 이유를 설명했다. 그리고 테스트 코드도 만들어보여주려고 했다! 그런데 실패했다... 다음 평가가 있었던터라 평가가 끝나면 테스트 코드를 작성해서 보여주겠다고 했다!
이런 저런 테스트를 해본 결과, 내가 알고 있는 이유와 비슷하지만 조금 다르다는 걸 알았다. 정확하지 않은 지식을 전달했던 것이다..!!
#include <iostream>
#include <iterator>
template <typename T>
class Base {
public:
typedef T a;
typedef std::string b;
};
template <typename T>
class Base2 {
public:
// 네임스페이스가 있으면 무조건 typename 이 필요
typedef typename Base<T>::a d; // 자료형 재정의
typename Base<T>::b e; // 변수 선언
// 없으면 상관 없음
typedef T f; // 자료형 재정의
T g; // 변수 선언
};
int main() {
Base2<std::string> test;
Base2<std::string>::d what = "hello";
test.e = "there!!";
test.g = "I am jaekim";
std::cout << what << " ";
std::cout << test.e << std::endl;
std::cout << test.g << std::endl;
}
Base
에서 자료형 T 를 a
로 std::string 을 b
로 바꿨다.
Base2
에서는 바꾼 a 를 d 로 바꿨다.
자료형 b 로 변수 e를 선언
했다.
Base
에서는 typename 이 없다
.
하지만 Base2
에서 Base 의 a 와 b 를 사용할 때는 typename 이 있다.
Base2 는 Base 에 있는 자료형을 불러와서 사용했기 때문에 typename 이 필요한 것이다.
Base2 의 f 와 g 를 보면, Base 가 갖고 있는 자료형을 사용하지 않기 때문에 typename을 사용하지 않는다.
정리하면,
typename은 template 에서 사용하는 키워드이다.
template 안에서 네임 페이스(ex. Base<T>::
)를 사용해서 자료형을 재정의하거나 변수를 선언하는 경우
typename 을 사용해야 한다는 것이다.
그래야 컴파일러가 자료형인지 아닌지 구분을 한다는 것이다. 위 예제 코드의 결과는 다음과 같다!
hello there!!
I am jaekim