2013-06-07 2 views
0

У меня есть класс, содержащий map, в котором хранятся векторы shared_ptr объектов.Итератор для векторных значений в std :: map

#include <map> 
#include <memory> 
#include <vector> 

template <class T, class U> 
class MyMap { 
public: 
    typedef std::shared_ptr<U> UPtr; 
    typedef std::vector<UPtr> UPtrVec; 
    typedef std::map<T, UPtrVec> VecMap; 
    ... 
private: 
    VecMap vec_map; 
}; 

Возможно ли создать итератор (используя boost, я полагаю) для значений внутри каждого отображаемого векторного значения? Я также хотел бы иметь возможность перебирать сохраненные значения для указанного списка ключей.

Например, если моя карта содержала данные, как это (переход на синтаксис Python для краткости)

// note: in actuality the vector contents are shared_ptr's to objects 
vec_map[5] = ["one", "two", "three"] 
vec_map[8] = ["four", "five"] 
vec_map[3] = ["six", "seven", "eight", "nine"] 

Можно ли написать интерфейс итератора таким образом, что я мог бы сделать следующее:

MyMap<int, std::string> mymap 
... 
for(auto it = mymap.begin(), it != mymap.end(); ++it) 
    cout << *it << " "; 

и иметь выход «один два три четыре пять шесть семь восемь девять»? Если бы я мог заставить это работать, я бы хотел написать итератор, который будет фильтровать на основе значений ключа.

Запрет на то, что я думал о создании другого UPtrVec в классе, который хранил все объекты UPtr в плоском списке. Но я теряю отображение, которое позволит мне фильтровать на основе значений ключа, если я не вложу информацию ключа в объекты U.

+2

* «И у вас есть выход» один два три четыре пять шесть семь восемь девять?? »* - Вы имеете в виду *« шесть семь восемь девять один два три четыре пять »*, верно? –

+0

Мимический стандартный контейнер (например, MyMap, MeVector, MyQueue и т. Д.) - непростая задача и часто задает вопросы дизайну. – maverik

+0

@ChristianRau хороший пункт! – jasonm76

ответ

1

Вы можете создать свой собственный итератор, используя стандартный C++:

Создать класс и наследовать, если iterator класс с помощью одного стандартного итератора тега (input_iterator_tag, output_iterator_tag, forward_iterator_tag, bidirectional_iterator_tag, random_access_iterator_tag) в зависимости от типа итератора вы хотите. (input_iterator_tag достаточно для образца, который вы показываете).

Внедрите в этом классе интерфейс итератора, требуемый типом. (В cppreference.com вы можете найти требования для каждого итератора).

class MyIterator: public std::iterator<input_iterator_tag, MyClass> { 
    // requirements for iterators 
    MyIterator(const MyIterator&); 
    MyIterator& operator=(const MyIterator&); // or any variant 
    ~MyIterator() noexcept; 
    MyClass& operator*() const; 
    MyIterator& operator++(); 

    // requirements for input iterators 
    MyClass* operator->(); 
    MyIterator operator++(int); 
}; 

// requirements for iterators 
bool operator==(const MyIterator& a, const MyIterator& b); 
// requirements for input iterators 
bool operator!=(const MyIterator& a, const MyIterator& b); 

Внедренная итератор должна иметь ссылку на используемую карту (или MyMap объекта, в зависимости от того, как вы ее реализации), к вектору на карте (например, с помощью итератора) и к элемент в векторе (опять же, например, используя итератор).

+0

Вы не наследуете от тега итератора, но имеете его как тип члена или специализацию 'std :: iterator_traits' (обычно это делается путем наследования от' std :: iterator'). –

+0

* «' input_iterator_tag' достаточно для образца, который вы показываете »* - Тем не менее было бы довольно странно * искусственно * ограничивать себя наименее полезным тегом итератора, учитывая, что' std :: forward_iterator_tag' * одинаково легко * для поддержки (или даже 'std :: bidirectional_iterator_tag'). –

+0

Спасибо ... Кажется, у меня есть чтение! – jasonm76

Смежные вопросы