Skip to content

Instantly share code, notes, and snippets.

@cjxgm
Created August 24, 2014 10:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cjxgm/a97ccde16db914b00604 to your computer and use it in GitHub Desktop.
Save cjxgm/a97ccde16db914b00604 to your computer and use it in GitHub Desktop.
test: iterator_range & custom iterator
#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