- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
#ifndef FILTER_H
#define FILTER_H
#include <cassert>
#include <vector>
#include <algorithm>
template<typename T>
class filter_container;
namespace detail {
template<typename Iter, typename Pred>
class filter {
public:
filter(Iter begin, Iter end, Pred pred) :_begin(begin), _end(end), _pred(pred) { }
filter(const filter & f) : _begin(f._begin), _end(f._end), _pred(f._pred) { }
filter & operator = (const filter & f) {
if(this != &f) {
_begin = f._begin;
_end = f._end;
_pred = f._pred;
}
return *this;
}
~filter() { }
class const_iterator {
public:
typedef typename Iter::reference reference;
typedef typename Iter::pointer pointer;
const_iterator(Iter iter, const filter & cont) :_iter(iter), _cont(&cont) { advance_until_pred(); }
const_iterator(const const_iterator & i) :_iter(i._iter), _cont(i._cont) { }
const_iterator & operator = (const const_iterator & i) {
if(this != &i) {
_iter = i._iter;
_cont = i._cont
}
return *this;
}
~const_iterator() { }
const_iterator & operator++() { advance_until_pred(); return *this; }
const_iterator operator++(int) {
const_iterator ret = *this;
advance_until_pred();
return ret;
}
const reference operator*() const { return *_iter; }
const pointer operator->() const { return &*_iter; }
bool operator == (const const_iterator & i) const {
assert(_cont == i._cont);
return _iter == i._iter;
}
bool operator != (const const_iterator & i) const { return !(*this == i); }
protected:
Iter _iter;
const filter * _cont;
private:
void advance_until_pred() {
if(_iter != _cont->_end) {
std::advance(_iter, 1);
}
_iter = std::find_if(_iter, _cont->_end, _cont->_pred);
}
private:
const_iterator();
};
class iterator : public const_iterator {
public:
iterator(Iter iter, const filter & cont) :const_iterator(iter, cont) { }
iterator(const iterator & i) :const_iterator(i) { }
iterator & operator = (const iterator & i) { const_iterator::operator=(i); return *this; }
~iterator() { }
reference operator*() { return *_iter; }
pointer operator->() { return &*_iter; }
private:
iterator();
};
iterator begin() { return iterator(_begin, *this); }
iterator end() { return iterator(_end, *this); }
const_iterator cbegin() const { return const_iterator(_begin, *this); }
const_iterator cend() const { return const_iterator(_end, *this); }
private:
Iter _begin, _end;
Pred _pred;
private:
filter();
};
}
template<typename Iter, typename Pred>
detail::filter<Iter, Pred> filter(Iter begin, Iter end, Pred pred) {
return detail::filter<Iter, Pred>(begin, end, pred);
}
#endif // FILTER_H
Тривиальная крестовщина, ничего выдающегося. Внезапно подумалось, что подобный контейнер был бы довольно удобен.
Мне просто любопытно, насколько быстро этот пост будет слит автоминусаторами :)
Xom94ok 29.04.2015 23:15 # 0
Ну, или оно по расписанию.
А слив комментариев в комплекте тоже есть?
LispGovno 30.04.2015 00:06 # 0
Xom94ok 30.04.2015 06:15 # +2
laMer007 30.04.2015 13:58 # 0
Liskov substitution principle тебе в ребро.
Наследование правильно применимо для реализации в отношения ЯВЛЯЕТСЯ
bormand 30.04.2015 14:03 # +2
А че не так то? Неконстантный оператор можно подставить вместо константного. Все операции, которые умел константный, на нём работать тоже будут. А то, что у него operator *() возвращает неконстантную ссылку - всем похуй, вместо константных они прокатят. Поэтому неконстантный итератор ЯВЛЯЕТСЯ частным случаем константного.
Xom94ok 30.04.2015 18:39 # 0
В бусте, оказывается, есть filter_iterator, но он без контейнера и, как мне кажется, тяжеловат - каждый инстанс хранит в себе предикат, исходный итератор и итератор на конец диапазона.
bormand 30.04.2015 07:48 # 0
P.S. В общем-то копирование, присваивание и деструктор тоже можно не писать, компилятор сам справится. Нафиг?
bormand 30.04.2015 07:53 # +1
TarasB 30.04.2015 10:59 # 0
bormand 30.04.2015 11:16 # 0
http://en.cppreference.com/w/cpp/iterator/iterator_tags
roman-kashitsyn 30.04.2015 11:31 # 0
laMer007 30.04.2015 14:02 # 0
Иной раз надо добавить другой конструктор и вот думай потом "постираются" ли прочие конструктора или не надо их добавлять руками, ибо компилятор сам справится
Xom94ok 30.04.2015 18:30 # 0
По привычке, чтобы самому не накосячить; аналогично с присваиванием, деструктором и копированием. Плюс там можно бряк поставить и отследить, когда они вызываются, что тоже иногда любопытно.
CkpunmoBbIu_nemyx 25.08.2021 17:55 # 0