에러 메세지는 다음과 같다.
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xfunctional(125): error C2784: 'bool std::operator <(const std::move_iterator<_RanIt> &,const std::move_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::move_iterator<_RanIt> &' from 'const CHARRANGE'
작업 환경 : Visual C++ 10.0 (VS2010) on Windows 7 Professional, SP1, (English)
F4 를 누르거나 위의 에러 메세지 출력 줄을 더블 클릭하면 다음과 같은 파일이 열린다.
118 // TEMPLATE STRUCT less
119 template<class _Ty>
120 struct less
121 : public binary_function<_Ty, _Ty, bool>
122 { // functor for operator<
123 bool operator()(const _Ty& _Left, const _Ty& _Right) const
124 { // apply operator< to operands
125 return (_Left < _Right);
126 }
127 };
에러가 난 줄은 125 번 째 인데, xfunctional 파일인데, 제공되는 파일이므로 당연히 여기서 문제가 될 일은 거의 없고, 따라서 문제는 내가 작성한 코드에 있어야 한다.
이제 추정을 해보자. 위의 125번째 줄은 operator< 를 [_Left] 와 [_Right] 의 operand 에 적용할 수 없었기 때문에 일어난 것이다. 위 에러 메세지를 보면 대략 CHARRANGE 라는 구조체에 이 연산자를 적용하려 했음을 알 수 있다. 내가 작성한 코드에는 그러나 operator< 를 호출하거나 less 를 함수 객체로 사용하는 곳이 없다. 대신,
36 template<class T>
37 bool uniq(std::vector<T>* v)
38 {
39 ASSERT( v != NULL);
40 if(v->empty() == true) return false;
41
42 std::set<T> s(v->begin(), v->end());
43 v->clear();
44 v->insert(v->begin(), s.begin(), s.end());
45
46 return true;
47 }
위와 같은 함수가 있고,
183 std::vector<CHARRANGE> herb_boundary;
184 find_boundary(herb_position, &herb_boundary);
185 uniq(&herb_boundary);
위처럼 uniq 함수를 호출하는 부분이 있다. 즉, 나는 CHARRANGE 구조체를 요소로 같는 herb_boundary 라는 변수를 만든 후, 이 변수를 uniq 함수에 전달하고, uniq 함수에서 이 요소들을 set 에 집어 넣으려 하고 있다. 문제는 set 의 경우 효율성을 위해 set 안에 들어가는 요소를 정렬을 해서 저장하게 되는데 이 때 binary search 를 이용한다. 따라서 요소의 대소비교가 가능해야 하기에 operator< 를 set 에 집어 넣는 요소에 적용하게 된다. 바로 이 부분이다. 이 부분에서 CHARRANGE 구조체에 적용할 operator< 가 없었기 때문에 set 에 집어 넣을 수 없었고, 그래서 컴파일 에러가 난 것이다. 1
어떻게 해결해야 할까? 보통 set 이나 map 처럼 operator< 를 사용하여 container 에 객체를 집어 넣을 경우, operator< 를 적용할 수 없는 요소를 집어 넣을 경우 두 가지 방법을 사용할 수 있다. 별도의 함수 객체를 만들어서 set 이나 map 의 정의시 함수 객체를 같이 써 주거나, 집어 넣을 요소의 클래스 자체에 operator< 를 정의해 주는 것이다. 나의 경우는 다음과 같이 전자를 따랐다.
49 class range_order{
50 public:
51 bool operator()(const CHARRANGE& op1, const CHARRANGE& op2) const
52 {
53 if(op1.cpMax == op2.cpMax){
54 return op1.cpMin < op2.cpMin;
55 }
56 else{
57 return op1.cpMax < op2.cpMax;
58 }
59 return false;
60 }
61 };
62
63 template<class T, class L>
64 bool uniq(std::vector<T>* v)
65 {
66 ASSERT( v != NULL);
67 if(v->empty() == true) return false;
68
69 std::set<T,L> s(v->begin(), v->end());
70 v->clear();
71 v->insert(v->begin(), s.begin(), s.end());
72
73 return true;
74 }
위처럼 함수 객체를 정의해 주고,
185 uniq<CHARRANGE,range_order>(&herb_boundary);
위처럼 호출해 준다. 즉, CHARRANGE 구조체를 받아서 순서를 정해 주는 함수 객체 range_order 를 정의해 준 후, uniq 함수에 이 함수 객체도 같이 제공해 주는 것이다. 이를 위해서, 요소의 타입과 그 타입의 순서를 정해 주는 함수 객체 두 개를 받는 uniq 함수를 추가해 준다.
아, ..., STL의 이 확장성이란.
- 코드 중 185 번 줄은 uniq<CHARRANGE>(&herb_boundary); 이어야 하는데, VC++ 의 경우 알아서 해주기도 한다. 내가 디버깅 하다 이 부분을 살짝 빼 먹은 것을 알았는데, VC++ 이 다 알아서 해주긴 해도 그래도 위처럼 명시적으로 써 주는 게 좋다. ㅋ. [본문으로]
'컴퓨터 > 디버깅' 카테고리의 다른 글
오랜 시행 후 프로그램이 멈추는 경우 - GDI 문제 (1) | 2013.01.01 |
---|---|
STL의 set 의 iterator 와 const_iterator에 따른 오류 (0) | 2012.12.06 |
a required resource was unavailable (0) | 2011.08.07 |
cannot convert ... (0) | 2011.06.23 |
discards qualifiers 에러 : STL의 map의 [] 연산자의 반환값 (0) | 2011.04.14 |