I wrote a class that wraps an iterator and returns converted values ββon request:
// iterator-wrapper.h template<class Iter, class Val, class Fct> class IteratorWrapper { Iter cur_; const Iter last_; const Fct fct_; public: IteratorWrapper(Iter first, Iter last, const Fct fct) : cur_(first), last_(last), fct_(fct) {} const Val Value() const {return fct_(*cur_);} void Next() {++cur_;} bool Done() const {return cur_ == last_;} };
Now the class can use it to return iterators over some functions of its data:
// mydata.h #include <map> #include "iterator-wrapper.h" class MyData { struct GetFirst { template<class T1, class T2> const T1& operator()(const std::pair<T1,T2>& aPair) const { return aPair.first; } }; struct GetSecond { template<class T1, class T2> const T2& operator()(const std::pair<T1,T2>& aPair) const { return aPair.second; } }; typedef std::string Key; typedef int Val; typedef std::map<Key, Val> Map; typedef Map::const_iterator MapIter; Map m_; public: typedef IteratorWrapper<MapIter, Key, GetFirst> KeysIter; typedef IteratorWrapper<MapIter, Val, GetSecond> ValuesIter; MyData() { // add some data m_["foo"] = 1; m_["bar"] = 2; } KeysIter GetKeys() const { return KeysIter(m_.begin(), m_.end(), GetFirst()); } ValuesIter GetValues() const { return ValuesIter(m_.begin(), m_.end(), GetSecond()); } };
And here is a usage example:
#include <iostream> #include "iterator-wrapper-data.h" int main() { MyData d; std::cout << "KEYS:" << std::endl; MyData::KeysIter kit = d.GetKeys(); for(; !kit.Done(); kit.Next()){ std::cout << kit.Value() << std::endl; } std::cout << "VALUES:" << std::endl; MyData::ValuesIter vit = d.GetValues(); for(; !vit.Done(); vit.Next()){ std::cout << vit.Value() << std::endl; } return 0; }
I have a few questions about this:
Is this a reasonable design, or can it be done more succinctly, perhaps using STL or boost? (I know there is boost::iterator_facade , but I found this code more complex than necessary, and I'm not sure if it does exactly what I want here.)
Why doesn't std::map contain something like this (I mean the keys() function, which returns an iterator over keys, etc.)? (Or that?)
What is wrong with returning a link, for example, const Val& Value() const (as opposed to returning by value, as in the first listing above)?
Frank source share