jasonm76
jasonm76

Reputation: 500

Iterator for vector values in a std::map

I have a class containing a map that stores vectors of shared_ptr objects.

#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;
};

Is it possible to create an iterator (using boost, I presume) for the values inside each mapped vector value? I would also like to be able to iterate over the stored values for a specified list of keys.

For example, if my map contained data like this (switching to Python syntax for brevity)

 // 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"]

Is it possible to write an iterator interface such that I could do the following:

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

and have it output "one two three four five six seven eight nine" ? If I could get that to work, I'd like to write an iterator that would filter based on key values.

Barring that I was think about creating another UPtrVec in the class that stored all UPtr objects in a flat list. But I lose the mapping that would allow me to filter based on key values, unless I embed the key info into the U objects.

Upvotes: 0

Views: 864

Answers (1)

Gonmator
Gonmator

Reputation: 780

You can create your own iterator just using standard C++:

Create a class and inherit if iterator class using one of the standard iterator tag (input_iterator_tag, output_iterator_tag, forward_iterator_tag, bidirectional_iterator_tag, random_access_iterator_tag) depending the type of iterator you want. (input_iterator_tag is enough for the sample you show).

Implement in that class the iterator interface required by the type. (In cppreference.com you can found the requirements for each iterator).

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

The implemented iterator should have a reference to the used map (or the MyMap object, depending on how do you implement it), to the vector in the map (for example, using an iterator) and to the element in the vector (again, for example, using an iterator).

Upvotes: 1

Related Questions