G++ - 템플릿 클래스의 iterator 코드 사용에서 발생하는 컴파일 오류
G++ 컴파일러로 다음의 코드를 컴파일 하면,
#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 MuliPartByteArray
{
_int key;
std::vector<BYTE> byteHolders;
_long totalSize;
public:
MuliPartByteArray(_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, MuliPartByteArray> MultiPartBytesMap;
MultiPartBytesMap receivedMultiPartedBytes;
public:
MultiPartByteArrayReceiver() : Super(), receivedMultiPartedBytes()
{}
void Test()
{
std::map<_int, MultiPartByteArray>::iterator iter = receivedMultiPartedBytes.find(1); // 컴파일 오류
}
};
using namespace std;
int main()
{
cout << "Hello World" << endl;
MultiPartByteArrayReceiver<int, int> t;
size_t size = t.receivedMultiPartedBytes.size();
return 0;
}
이런 컴파일 오류가 발생합니다.
main.cpp: In member function void MultiPartByteArrayReceiver<Receiver, ErrorAction, MAX_CONTENT_SIZE>::Test():
main.cpp:60:28: error: MultiPartByteArray was not declared in this scope
std::map<_int, MultiPartByteArray>::iterator iter = receivedMultiPartedBytes.find(1);
^
main.cpp:60:46: error: template argument 2 is invalid
std::map<_int, MultiPartByteArray>::iterator iter = receivedMultiPartedBytes.find(1);
^
main.cpp:60:46: error: template argument 4 is invalid
main.cpp:60:58: error: expected initializer before iter
std::map<_int, MultiPartByteArray>::iterator iter = receivedMultiPartedBytes.find(1);
^
아~~~ 이 현란한 C++ template 사용이여~~~~!
위의 컴파일 오류를 보여준 직장 동료의 우회 방법은 MultiPartByteArrayReceiver 클래스 내에 inner 클래스로 정의된 MuliPartByteArray를 바깥으로 빼내는 것이었습니다.
#include <iostream>
#include <vector>
#include <map>
// ... [생략]...
class MuliPartByteArray
{
// ... [생략]...
};
template<class Receiver, class ErrorAction, _int MAX_CONTENT_SIZE = 8192>
class MultiPartByteArrayReceiver : public KeepAliveReceiver< MultiPartByteArrayReceiver<Receiver, ErrorAction>, ErrorAction>
{
// ... [생략]...
};
// ... [생략]...
그런데... 사실 inner 클래스는 이유가 있기 때문에 inner 클래스가 된 것인데 그것을 바깥으로 빼내는 것은 그리 바람직해 보이지 않았습니다. 제가 제시한 해결책은 클래스의 전방 선언이었는데, 다음과 같이 처리하는 것이었습니다.
#include <iostream>
#include <vector>
#include <map>
// ... [생략]...
class MuliPartByteArray;
template<class Receiver, class ErrorAction, _int MAX_CONTENT_SIZE = 8192>
class MultiPartByteArrayReceiver : public KeepAliveReceiver< MultiPartByteArrayReceiver<Receiver, ErrorAction>, ErrorAction>
{
class MuliPartByteArray
{
// ... [생략]...
};
// ... [생략]...
};
// ... [생략]...
이렇게 해주면 컴파일이 잘 됩니다. 직장 동료가 이유를 물었지만... 허허허~~~ 어찌 그것을 제가 알 수 있겠습니까? 단지 과거에 C++ template과 잠시 싸워 온 일종의 감각으로 전방 선언이 효력이 있을 거라는 생각을 했을 뿐입니다. (혹시, 명확한 이유를 알고 계신 분이 있다면 덧글 좀~~~~ ^^)
참고로, 이 예제의 코드는 Visual C++ 2013에서는 전방 선언 필요없이도 잘 컴파일됩니다.
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]