Post

C++ Template 의 inner class 로 type 선언 하기

주의 사항

이 글은 예전 블로그에서 옮겨온 오래 된 글입니다. 현재 상황과는 다를 수 있으며, 잘못 된 정보가 있을 수 있습니다.


정성태님의 홈페이지를 정독하던중 오랫만에 C++ 관련 글이 하나 올라 왔길래 확인해 보았습니다. 바로 g++에서 inner 클래스를 사용한 템플릿이 제대로 선언 되지 않는다는 문제인데요, 코드는 아래와 같습니다(조금 다릅니다. 원본에 오타가 있어서 좀 고쳣습니다)

원본 : http://www.sysnet.pe.kr/Default.aspx?mode=2&sub=0&pageno=0&detail=1&wid=1791

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <vector>
#include <map>

typedef char BYTE;
typedef int _int;
typedef std::vector<BYTE> _byteArrayHolder;
typedef long _long;

template <class T, class V>
class KeepAliveReceiver
{
};

template<class Receiver, class ErrorAction, _int MAX_CONTENT_SIZE = 8192>
class MultiPartByteArrayReceiver : public KeepAliveReceiver< MultiPartByteArrayReceiver<Receiver, ErrorAction>, ErrorAction>
{
	class MultiPartByteArray
	{
	public:
		_int key;
		std::vector<BYTE> byteHolders;
		_long totalSize;

	public:
		MultiPartByteArray(_int _key) : key(_key), byteHolders(), totalSize(0)
		{
		}

		void AddBytes(_byteArrayHolder bytes)
		{
			totalSize += bytes.size();
		}
	};

	typedef KeepAliveReceiver< MultiPartByteArrayReceiver<Receiver, ErrorAction, MAX_CONTENT_SIZE>, ErrorAction> Super;
	typedef MultiPartByteArrayReceiver<Receiver, ErrorAction, MAX_CONTENT_SIZE> This;

public:
	typedef std::map<_int, MultiPartByteArray>  MultiPartBytesMap;
	MultiPartBytesMap receivedMultiPartedBytes;

public:

	MultiPartByteArrayReceiver() : Super(), receivedMultiPartedBytes()
	{}

	void Test()
	{
		MultiPartByteArray a(1);
		std::map<_int, MultiPartByteArray>::iterator iter = receivedMultiPartedBytes.find(1); //컴파일 오류
	}
};

int main()
{
	std::cout << "Hello World" << std::endl;

	MultiPartByteArrayReceiver<int, int> t;
	t.Test();

	return 0;
}

바로 위와 같은 코드인데, 이는 template 이 완전히 생성 되기 전에, 그 템플릿에 의존하는 type을 인식할 수 없기 때문에 발생합니다 (이런 경우는 템플릿 클래스가 부모 템플릿의 함수를 호출한다거나 할때도 발생합니다)

VC++은 그냥 적당히 알아서 (…) 인식해서 넘어 가는데 이걸 오류로 처리하는 컴파일러도 있습니다. 뭐 만드는사람 취향문제겟지만.

이 문제의 해결법은 바로 type을 인식하지 못하는 것이니 이게 template의 type 명을 나타낸다고 알려주는겁니다. 바로 typename 키워드를 쓰는것인데 그럼 아래와 같게 됩니다

1
typename std::map<_int, MultiPartByteArray>::iterator iter = receivedMultiPartedBytes.find(1); //컴파일 오류 

이렇게 하면 뒤의 템플릿 선언문을 타입으로 인식하여 정상적으로 컴파일 됩니다. 물론 VC에서도 마찬가지입니다. 또 템플릿을 선언 할 때 처럼 class 키워드를 써도 OK 입니다. 전 typename 키워드가 헤깔리지 않아 선호하는 편이지만요

PS. 사실 이 모든 문법적 지저분함을 해결하는 마법의 키워드가 C++에 있으니…

그냥 auto 쓰면 됩니다 (…) C++11에서 추가된 auto와 decltype 의 타입추론 시스템은 템플릿을 정말 간단하게 만들어주는 축복이지요

This post is licensed under CC BY 4.0 by the author.