2008-09-26 8 views
2

일부 C++ 연산자 오버로드 구문을 이해하는 데 도움이 필요합니다. (C++ 맵에 대한 연산자 오버로드

struct iterator : public map_t::iterator 
{ 
    iterator() {} 
    iterator(const map_t::iterator & it) 
     : map_t::iterator(it) {} 
    iterator(const iterator & it) 
     : map_t::iterator(
      *static_cast<const map_t::iterator *>(&it)) {} 
    operator key_t() {return ((this->operator*()).first);}   // I don't understand this. 
    operator ipdc_t*() const {return ((this->operator*()).second);} // or this. 

}; 

그리고 begin()과 end() 시작 반환)하고 :

클래스의 작성자가 내부 맵 구조에 대한 반복자를 만들었습니다

template <class key_t, class ipdc_t> 
class ipdc_map_template_t : public ipdc_lockable_t 
{ 
    ... 
    typedef map<key_t, 
      ipdc_t*, 
      less<key_t>> map_t; 
    ... 
이 : 클래스는 다음과 같이 선언 지도의 끝() :

iterator begin() {IT_ASSERT(is_owner()); return map.begin();} 
iterator end() {return map.end();} 

내 질문은 내가 반복자가있는 경우, 어떻게 키와 값을 얻기 위해 그 오버로드를 사용합니까입니까?

ipdc_map_template_t::iterator iter; 
    for(iter = my_instance.begin(); 
      iter != my_instance.end(); 
     ++iter) 
    { 
     key_t my_key = ??????; 
     ipdc_t *my_value = ??????; 

    } 
+0

용액이 충분하다 : 당신은 아직도 (I 더 읽기 찾기) 원래의 접근을 std::map::iterator의 서브 클래스 사용할 수있다 그래서 어쨌든 : 암시 적 캐스트를 문법적 설탕으로 사용하는 것은 나쁘고 위험한 디자인입니다. IMHO ... – paercebal

답변

6

이 캐스트하는 사업자 : 그래서, 클래스에 정의 된 반복자 주어, 당신은 단순히 변수를 할당 할 수 있어야한다 값, 체육에 대한 포인터 문제가 있지만 함께 (아래 제공

{ 
    key_t key = (*iter).first; 
    ipdc_t *val = (*iter).second; 

    // or, equivalently 
    key_t key = iter->first; 
    ipdc_t *val = iter->second; 

} 
+0

iter-> 처음에는 괄호가 필요 없기 때문에 (* iter). –

+0

그렉의 버전이 마음에 들지만, 어쨌든, 캐스트 연산자 오버로딩의 오용을 통해 해킹하는 대신 std :: map 표준 인터페이스를 사용하는 것이 가독성에 대해 옳습니다 ... – paercebal

2

클래스 작성자가 캐스트 연산자를 재정의했습니다. iter를 올바른 유형의 객체에 할당하면 메서드를 통해 올바른 값으로 자동 캐스팅해야합니다.

N.B. : 값 유형이 포인터로 저장됩니다. 따라서 값을 추출 할 때 맵 인터페이스에서 지정한 값 유형에 대한 포인터를 지정해야합니다.

typedef ipdc_map_template_t<int,std::string> MyMap; 
MyMap mymap; 

for(MyMap::iterator iter = mymap.begin(); 
        iter != mymap.end(); 
        ++iter) 
    { 
      int   my_key = iter; 
      std::string* my_value = iter; 

    } 

여기에 나와있는 방향에 동의합니다. 이렇게하면 코드를 읽기 쉽도록 만드십니까? 구식 맵 반복기를 사용하면 더 유용 할 것 같습니다. 이 컨테이너가 필요한 특수 라이브러리에 정의되어 있습니까? 아니면 부스트 포인터 컨테이너를 살펴 보는 것이 좋을까요?

+0

코드를 검증 해 주시겠습니까? 당신이 옳다고 생각 하나 :지도는 값의 포인터를 조작하는 것이지 값 자체를 조작하는 것이 아닙니다. 그래서 사용자는 "std :: string * my_value = iter;"를해야 할 것입니다. 아니면 ... 나는 잠을 자러 가야 할 것 같습니다. :-p – paercebal

+0

그냥 그렇게 생각했습니다. 그러나 클래스의 부분적인 정의 만 얻으면 코드를 검증하기가 어렵습니다. –

+0

오른쪽 ... :-p ... 어쨌든, +1 ... – paercebal

2

연산자 key_t()와 연산자 ipdc_t *()는 모두 캐스트 정의입니다. ipdc_map_template::iterator 이후,

{ 
    key_t key = iter; 
    ipdc_t *val = iter; 
} 

을 또는 :이 작업을 수행 할 수 있도록

ipdc_map_template_t::iterator iter; 
    for(iter = my_instance.begin(); 
     iter != my_instance.end(); 
     ++iter) 
    { 
      key_t my_key = iter; 
      ipdc_t my_value = iter; 
    }