2008-09-26 3 views
2

Мне нужна помощь в понимании некоторых операторов перегрузки операторов C++. Класс объявлен как это:Перегрузка оператора для карт C++

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; 
    ... 

Создатель класса создал итератор для внутренней структуры карты:

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. 

}; 

И начать() и конец() возвращают начать() и конец() карты:

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

решения, предлагаемые ниже достаточно хороши (с, но проблема указатель на значение, ре рапс), поэтому In не будет разрабатывать ... Но в любом случае: Использование неявных отливок в качестве синтаксического сахара - плохой и опасный дизайн, IMHO ... – paercebal

ответ

6

Эти приведения типов операторов, так что вы можете сделать это:

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

Или, так как ipdc_map_template::iterator является подклассом std::map::iterator, вы все еще можете использовать оригинальные аксессоров (которые я нахожу более удобным для чтения):

{ 
    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). Сначала IMO, так как он избавляется от необходимости в круглых скобках. –

+0

Мне нравится версия Грега, но, во всяком случае, вы правы в отношении удобочитаемости использования стандартного интерфейса std :: map вместо того, чтобы взломать свой путь из-за неправильного использования перегрузки оператора броска ... – paercebal

2

Создатель класса переопределил операторы литья. Таким образом, просто назначив итера объекту правильного типа, он должен автоматически преобразовать себя с помощью методов в правильные значения.

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_t::iterator iter; 
    for(iter = my_instance.begin(); 
     iter != my_instance.end(); 
     ++iter) 
    { 
      key_t my_key = iter; 
      ipdc_t my_value = iter; 
    } 
Смежные вопросы