Я пытаюсь написать адаптер итератора, который должен вызывать функцию-член (или доступ к члену объекта) каждый раз, когда он разыменован. Вот пример такого API:Адаптер Iterator, который вызывает функцию-член при разыменовании
vector<pair<int,int>> ps = {{1,"a"}, {2,"b"}, {3,"c"}};
// Pairs that represent ranges
auto rf = make_adaptor(ps.begin(), ps.end(), [](const auto& x) {return x.first;}
auto rs = make_adaptor(ps.begin(), ps.end(), [](auto& x) {return x.second;}
Если распечатать 123
:
for_each(rf.first, rf.second, [](const auto& x){std::cout << x;});
Если установить каждый second
элемент пары в ps
:
for_each(rs.first, rs.second, [](auto& x){ x = "hello";});
Я пытался писать собственный тип iterator
вместе с методом make_adaptor
, но я не могу заставить его работать:
template <typename Iterator, typename UnaryOp>
struct adaptor {
using value_type = std::result_of<UnaryOp(typename Iterator::reference)>::type;
using reference = value_type&;
using pointer = value_type*;
using difference_type = typename Iterator::difference_type;
using iterator_category = typename Iterator::iterator_category;
adaptor(){};
adaptor(Iterator it, UnaryOp func) : _it(it), _func(func) {}
reference operator*() const { return _func(*_it); }
pointer operator->() const { return &_func(*_it); }
bool operator==(const adaptor& other) const { return _it == other._it; }
bool operator!=(const adaptor& other) const { return _it != other._it; }
adaptor& operator++() {
++_it;
return *this;
}
Iterator _it;
UnaryOp _func;
};
template <typename Iterator, typename UnaryOp>
auto make_adaptor(Iterator first, Iterator last, UnaryOp func) {
return std::make_pair(adaptor<Iterator, UnaryOp>(first, func),
adaptor<Iterator, UnaryOp>(last, func));
};
Причина этого заключается в следующем: Допустим, у меня есть алгоритм convex_hull
, который работает на points
. Но теперь у меня есть объекты, которые содержат points
в качестве участника (struct A { points pos;};
). Я хочу позвонить convex_hull
в коллекцию A
s.
Примечание: 'operator->' возвращает адрес из временного, а также '' оператор * возвращает оборванных ссылку. – Zereges
Это одна из проблем, с которыми я столкнулся, к сожалению, я не знаю, как их решить в общем виде. – fuji
Я бы определенно кэшировал результат вызова функции, поскольку вы, вероятно, не хотите вычислять 'func' каждый раз, когда итератор получает разыменованные. Затем вы можете вернуть переменную cahced (или ее адрес) и комментарий, что * приращение адаптера приведет к ее недействительности. * – Zereges