Я написал класс, который упаковывает итератор и возвращает преобразованные значения по требованию:
// 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_;}
};
Теперь класс может использовать его для возврата итераторов по некоторым функциям своих данных:
// 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());
}
};
И, вот пример использования:
#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;
}
У меня есть несколько вопросов по этому поводу:
Это разумный дизайн, или можно сделать его более кратко, возможно, используя STL или поддержку? (Я знаю, что есть boost::iterator_facade
, но я нашел этот код более сложным, чем необходимо, и я не уверен, что он выполняет именно то, что я хочу здесь.)
Почему std::map
не содержит ничего подобного для начала (я имею в виду функцию keys()
, которая возвращает итератор по ключам и т. Д.)? (Или это?)
Что не так с возвратом ссылки, например const Val& Value() const
(в отличие от возврата по значению, как в первом листинге выше)?