Reputation: 12692
I have some templates which can either have a map or a vector as underlying container. I would like the template to be able to expose const iterators to the elements. Most information I have read on how to expose iterators (such as this accu article) uses a form of
typedef std::vector<int>::iterator iterator;
typedef std::vector<int>::const_iterator const_iterator;
iterator begin() { return values.begin(); }
iterator end() { return values.end(); }
That doesn't really work for the template that uses the map though, because to access elements, the template can't use it->SomeMemberFunc()
anymore, but rather needs to use it->second.SomeMemberFunc()
. So I am looking to expose an iterator to the map elements which doesn't give access to the keys
but only the values of the map.
How would I accomplish this?
Upvotes: 4
Views: 941
Reputation: 56549
A workaround1
#include <map>
#include <iterator>
template <typename Iter>
struct map_iterator : public std::iterator<std::bidirectional_iterator_tag,
typename Iter::value_type::second_type>
{
map_iterator() {}
map_iterator(Iter j) : i(j) {}
map_iterator& operator++() { ++i; return *this; }
map_iterator& operator--() { --i; return *this; }
bool operator==(map_iterator j) const { return i == j.i; }
bool operator!=(map_iterator j) const { return !(*this == j); }
typename map_iterator::reference operator*() { return i->second; }
typename map_iterator::pointer operator->() { return &i->second; }
map_iterator operator--(int) { return std::prev(--(*this)); }
map_iterator operator++(int) { return std::next((++*this)); }
protected:
Iter i;
};
template <typename Iter>
inline map_iterator<Iter> make_map_iterator(Iter j) {
return map_iterator<Iter>(j);
}
And then
int main() {
std::map<int,std::string> m {{1, "Hi"},{2, "Bye"}};
for (auto i=make_map_iterator(m.begin()); i!=make_map_iterator(m.end());i++)
cout << *i << endl;
}
Upvotes: 2