Created
August 24, 2014 10:43
-
-
Save cjxgm/a97ccde16db914b00604 to your computer and use it in GitHub Desktop.
test: iterator_range & custom iterator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <list> | |
using namespace std; | |
template <class Iterator> | |
struct iterator_range | |
{ | |
using iterator = Iterator; | |
iterator_range(iterator _begin, iterator _end) | |
: _begin{_begin}, _end{_end} {} | |
const iterator& cbegin() const { cout << "cbegin" << endl; return _begin; } | |
const iterator& cend() const { return _end; } | |
iterator& begin() { cout << "begin" << endl; return _begin; } | |
iterator& end() { return _end; } | |
private: | |
iterator _begin; | |
iterator _end; | |
}; | |
template <class Iterator> | |
decltype(auto) make_iterator_range(Iterator begin, Iterator end) | |
{ | |
return iterator_range<Iterator>(begin, end); | |
} | |
struct primitive | |
{ | |
virtual void render() = 0; | |
virtual void damage(bool val=true) { _damaged = val; } | |
virtual bool damaged() { return _damaged; } | |
private: | |
bool _damaged = true; | |
}; | |
struct rect : public primitive | |
{ | |
rect() { my = i++; } | |
void render() override { damage(false); cout << "render rect " << my << endl; } | |
private: | |
int my; | |
static int i; | |
}; | |
int rect::i; | |
struct fill : public primitive | |
{ | |
fill() { my = i++; } | |
void render() override { damage(false); cout << "render fill " << my << endl; } | |
private: | |
int my; | |
static int i; | |
}; | |
int fill::i; | |
struct scene | |
{ | |
using value_type = primitive*; | |
using list_type = std::list<value_type>; | |
using iterator = list_type::iterator; | |
struct damaged_iterator | |
: public std::iterator<std::forward_iterator_tag, value_type> | |
{ | |
using iterator = scene::iterator; | |
using self_type = damaged_iterator; | |
damaged_iterator(iterator c, iterator end) : c(c), end(end) | |
{ | |
validate(); | |
} | |
value_type& operator*() { return *c; } | |
self_type& operator++() | |
{ | |
++c; | |
validate(); | |
return *this; | |
} | |
bool operator!=(const self_type& other) { return (c != other.c); } | |
private: | |
iterator c; | |
iterator end; | |
void validate() | |
{ | |
while (c != end && !(*c)->damaged()) | |
++c; | |
} | |
}; | |
using damaged_range = iterator_range<damaged_iterator>; | |
damaged_range damaged() { return {damaged_begin(), damaged_end()}; } | |
damaged_iterator damaged_begin() { return {begin(), end()}; } | |
damaged_iterator damaged_end() { return { end(), end()}; } | |
iterator begin() { return childs.begin(); } | |
iterator end() { return childs.end (); } | |
void render() | |
{ | |
for (auto child: damaged()) | |
child->render(); | |
} | |
iterator rect() { return childs.insert(childs.end(), new ::rect); } | |
iterator fill() { return childs.insert(childs.end(), new ::fill); } | |
private: | |
list_type childs; | |
}; | |
int main() | |
{ | |
scene s; | |
s.rect(); | |
s.rect(); | |
s.fill(); | |
auto r1 = s.rect(); | |
s.rect(); | |
s.fill(); | |
auto r2 = s.fill(); | |
s.rect(); | |
s.fill(); | |
s.fill(); | |
s.render(); | |
(*r1)->damage(); | |
s.render(); | |
s.render(); | |
(*r2)->damage(); | |
s.render(); | |
s.render(); | |
s.render(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment