#include <iostream>
#include <iterator>
#include <vector>
template <class Derived, class Category, class Value, class Reference = Value&,
class Pointer = Value*, class Distance = std::ptrdiff_t>
class iterator_facade;
struct iterator_core_access {
template <class I>
static typename I::reference dereference(const I& i) { return i.dereference(); }
template <class I>
static void increment(I& i) { i.increment(); }
template <class I>
static void decrement(I& i) { i.decrement(); }
template <class I1, class I2>
static bool equal(const I1& i1, const I2& i2) { return i1.equals(i2); }
};
namespace detail {
template <class Iterator, class Category, class Value, class Reference,
class Pointer, class Distance>
class iterator_facade_base;
template <class I, class V, class R, class P, class D>
class iterator_facade_base<I, std::output_iterator_tag, V, R, P, D>
: public std::iterator<std::output_iterator_tag, V, D, P, R> {
public:
R operator * () const { return iterator_core_access::dereference(derived()); }
I& operator ++ () {
iterator_core_access::increment(derived());
return derived();
}
I operator ++ (int) {
I copy = derived();
++*this;
return copy;
}
protected:
I& derived() { return *static_cast<I*>(this); }
const I& derived() const { return *static_cast<const I*>(this); }
};
template <class I, class V, class R, class P, class D>
class iterator_facade_base<I, std::input_iterator_tag, V, R, P, D>
: public iterator_facade_base<I, std::output_iterator_tag, V, R, P, D> {
public:
using iterator_category = std::input_iterator_tag;
P operator -> () const { return *iterator_core_access::dereference(this->derived()); }
};
template <class I, class V, class R, class P, class D>
class iterator_facade_base<I, std::forward_iterator_tag, V, R, P, D>
: public iterator_facade_base<I, std::input_iterator_tag, V, R, P, D> {
public:
using iterator_category = std::forward_iterator_tag;
};
template <class I, class V, class R, class P, class D>
class iterator_facade_base<I, std::bidirectional_iterator_tag, V, R, P, D>
: public iterator_facade_base<I, std::forward_iterator_tag, V, R, P, D> {
public:
using iterator_category = std::bidirectional_iterator_tag;
I& operator -- () {
iterator_core_access::decrement(this->derived());
return this->derived();
}
I operator -- (int) {
I copy = this->derived();
--*this;
return copy;
}
};
} // namespace detail
template <class I, class C, class V, class R, class P, class D>
class iterator_facade : public detail::iterator_facade_base<I, C, V, R, P, D> {};
template <typename Integer, bool INCREMENT = true>
class integer_iterator : public iterator_facade<integer_iterator<Integer, INCREMENT>,
std::input_iterator_tag, Integer, const Integer, Integer*, Integer> {
public:
explicit integer_iterator() : value_() {}
explicit integer_iterator(Integer value) : value_(value) {}
private:
friend struct iterator_core_access;
const Integer dereference() const { return value_; }
void increment() { INCREMENT ? ++value_ : --value_; }
bool equals(const integer_iterator& other) const { return value_ == other.value_; }
Integer value_;
};
int main() {
std::cout << std::is_same<integer_iterator<int>::iterator_category, std::input_iterator_tag>::value << std::endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8aXRlcmF0b3I+CiNpbmNsdWRlIDx2ZWN0b3I+Cgp0ZW1wbGF0ZSA8Y2xhc3MgRGVyaXZlZCwgY2xhc3MgQ2F0ZWdvcnksIGNsYXNzIFZhbHVlLCBjbGFzcyBSZWZlcmVuY2UgPSBWYWx1ZSYsCiAgICBjbGFzcyBQb2ludGVyID0gVmFsdWUqLCBjbGFzcyBEaXN0YW5jZSA9IHN0ZDo6cHRyZGlmZl90PgpjbGFzcyBpdGVyYXRvcl9mYWNhZGU7CgpzdHJ1Y3QgaXRlcmF0b3JfY29yZV9hY2Nlc3MgewogICAgdGVtcGxhdGUgPGNsYXNzIEk+CiAgICBzdGF0aWMgdHlwZW5hbWUgSTo6cmVmZXJlbmNlIGRlcmVmZXJlbmNlKGNvbnN0IEkmIGkpIHsgcmV0dXJuIGkuZGVyZWZlcmVuY2UoKTsgfQoKICAgIHRlbXBsYXRlIDxjbGFzcyBJPgogICAgc3RhdGljIHZvaWQgaW5jcmVtZW50KEkmIGkpIHsgaS5pbmNyZW1lbnQoKTsgfQoKICAgIHRlbXBsYXRlIDxjbGFzcyBJPgogICAgc3RhdGljIHZvaWQgZGVjcmVtZW50KEkmIGkpIHsgaS5kZWNyZW1lbnQoKTsgfQoKICAgIHRlbXBsYXRlIDxjbGFzcyBJMSwgY2xhc3MgSTI+CiAgICBzdGF0aWMgYm9vbCBlcXVhbChjb25zdCBJMSYgaTEsIGNvbnN0IEkyJiBpMikgeyByZXR1cm4gaTEuZXF1YWxzKGkyKTsgfQp9OwoKbmFtZXNwYWNlIGRldGFpbCB7Cgp0ZW1wbGF0ZSA8Y2xhc3MgSXRlcmF0b3IsIGNsYXNzIENhdGVnb3J5LCBjbGFzcyBWYWx1ZSwgY2xhc3MgUmVmZXJlbmNlLAogICAgY2xhc3MgUG9pbnRlciwgY2xhc3MgRGlzdGFuY2U+CmNsYXNzIGl0ZXJhdG9yX2ZhY2FkZV9iYXNlOwoKdGVtcGxhdGUgPGNsYXNzIEksIGNsYXNzIFYsIGNsYXNzIFIsIGNsYXNzIFAsIGNsYXNzIEQ+CmNsYXNzIGl0ZXJhdG9yX2ZhY2FkZV9iYXNlPEksIHN0ZDo6b3V0cHV0X2l0ZXJhdG9yX3RhZywgViwgUiwgUCwgRD4KICAgIDogcHVibGljIHN0ZDo6aXRlcmF0b3I8c3RkOjpvdXRwdXRfaXRlcmF0b3JfdGFnLCBWLCBELCBQLCBSPiB7CnB1YmxpYzoKICAgIFIgb3BlcmF0b3IgKiAoKSBjb25zdCB7IHJldHVybiBpdGVyYXRvcl9jb3JlX2FjY2Vzczo6ZGVyZWZlcmVuY2UoZGVyaXZlZCgpKTsgfQoKICAgIEkmIG9wZXJhdG9yICsrICgpIHsKICAgICAgICBpdGVyYXRvcl9jb3JlX2FjY2Vzczo6aW5jcmVtZW50KGRlcml2ZWQoKSk7CiAgICAgICAgcmV0dXJuIGRlcml2ZWQoKTsKICAgIH0KCiAgICBJIG9wZXJhdG9yICsrIChpbnQpIHsKICAgICAgICBJIGNvcHkgPSBkZXJpdmVkKCk7CiAgICAgICAgKysqdGhpczsKICAgICAgICByZXR1cm4gY29weTsKICAgIH0KCnByb3RlY3RlZDoKICAgIEkmIGRlcml2ZWQoKSB7IHJldHVybiAqc3RhdGljX2Nhc3Q8SSo+KHRoaXMpOyB9CgogICAgY29uc3QgSSYgZGVyaXZlZCgpIGNvbnN0IHsgcmV0dXJuICpzdGF0aWNfY2FzdDxjb25zdCBJKj4odGhpcyk7IH0KfTsKCnRlbXBsYXRlIDxjbGFzcyBJLCBjbGFzcyBWLCBjbGFzcyBSLCBjbGFzcyBQLCBjbGFzcyBEPgpjbGFzcyBpdGVyYXRvcl9mYWNhZGVfYmFzZTxJLCBzdGQ6OmlucHV0X2l0ZXJhdG9yX3RhZywgViwgUiwgUCwgRD4KICAgIDogcHVibGljIGl0ZXJhdG9yX2ZhY2FkZV9iYXNlPEksIHN0ZDo6b3V0cHV0X2l0ZXJhdG9yX3RhZywgViwgUiwgUCwgRD4gewpwdWJsaWM6CiAgICB1c2luZyBpdGVyYXRvcl9jYXRlZ29yeSA9IHN0ZDo6aW5wdXRfaXRlcmF0b3JfdGFnOwoKICAgIFAgb3BlcmF0b3IgLT4gKCkgY29uc3QgeyByZXR1cm4gKml0ZXJhdG9yX2NvcmVfYWNjZXNzOjpkZXJlZmVyZW5jZSh0aGlzLT5kZXJpdmVkKCkpOyB9Cn07Cgp0ZW1wbGF0ZSA8Y2xhc3MgSSwgY2xhc3MgViwgY2xhc3MgUiwgY2xhc3MgUCwgY2xhc3MgRD4KY2xhc3MgaXRlcmF0b3JfZmFjYWRlX2Jhc2U8SSwgc3RkOjpmb3J3YXJkX2l0ZXJhdG9yX3RhZywgViwgUiwgUCwgRD4KICAgIDogcHVibGljIGl0ZXJhdG9yX2ZhY2FkZV9iYXNlPEksIHN0ZDo6aW5wdXRfaXRlcmF0b3JfdGFnLCBWLCBSLCBQLCBEPiB7CnB1YmxpYzoKICAgIHVzaW5nIGl0ZXJhdG9yX2NhdGVnb3J5ID0gc3RkOjpmb3J3YXJkX2l0ZXJhdG9yX3RhZzsKfTsKCnRlbXBsYXRlIDxjbGFzcyBJLCBjbGFzcyBWLCBjbGFzcyBSLCBjbGFzcyBQLCBjbGFzcyBEPgpjbGFzcyBpdGVyYXRvcl9mYWNhZGVfYmFzZTxJLCBzdGQ6OmJpZGlyZWN0aW9uYWxfaXRlcmF0b3JfdGFnLCBWLCBSLCBQLCBEPgogICAgOiBwdWJsaWMgaXRlcmF0b3JfZmFjYWRlX2Jhc2U8SSwgc3RkOjpmb3J3YXJkX2l0ZXJhdG9yX3RhZywgViwgUiwgUCwgRD4gewpwdWJsaWM6CiAgICB1c2luZyBpdGVyYXRvcl9jYXRlZ29yeSA9IHN0ZDo6YmlkaXJlY3Rpb25hbF9pdGVyYXRvcl90YWc7CgogICAgSSYgb3BlcmF0b3IgLS0gKCkgewogICAgICAgIGl0ZXJhdG9yX2NvcmVfYWNjZXNzOjpkZWNyZW1lbnQodGhpcy0+ZGVyaXZlZCgpKTsKICAgICAgICByZXR1cm4gdGhpcy0+ZGVyaXZlZCgpOwogICAgfQoKICAgIEkgb3BlcmF0b3IgLS0gKGludCkgewogICAgICAgIEkgY29weSA9IHRoaXMtPmRlcml2ZWQoKTsKICAgICAgICAtLSp0aGlzOwogICAgICAgIHJldHVybiBjb3B5OwogICAgfQp9OwoKfSAgLy8gbmFtZXNwYWNlIGRldGFpbAoKdGVtcGxhdGUgPGNsYXNzIEksIGNsYXNzIEMsIGNsYXNzIFYsIGNsYXNzIFIsIGNsYXNzIFAsIGNsYXNzIEQ+CmNsYXNzIGl0ZXJhdG9yX2ZhY2FkZSA6IHB1YmxpYyBkZXRhaWw6Oml0ZXJhdG9yX2ZhY2FkZV9iYXNlPEksIEMsIFYsIFIsIFAsIEQ+IHt9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIEludGVnZXIsIGJvb2wgSU5DUkVNRU5UID0gdHJ1ZT4KY2xhc3MgaW50ZWdlcl9pdGVyYXRvciA6IHB1YmxpYyBpdGVyYXRvcl9mYWNhZGU8aW50ZWdlcl9pdGVyYXRvcjxJbnRlZ2VyLCBJTkNSRU1FTlQ+LAogICAgc3RkOjppbnB1dF9pdGVyYXRvcl90YWcsIEludGVnZXIsIGNvbnN0IEludGVnZXIsIEludGVnZXIqLCBJbnRlZ2VyPiB7CnB1YmxpYzoKICAgIGV4cGxpY2l0IGludGVnZXJfaXRlcmF0b3IoKSA6IHZhbHVlXygpIHt9CgogICAgZXhwbGljaXQgaW50ZWdlcl9pdGVyYXRvcihJbnRlZ2VyIHZhbHVlKSA6IHZhbHVlXyh2YWx1ZSkge30KCnByaXZhdGU6CiAgICBmcmllbmQgc3RydWN0IGl0ZXJhdG9yX2NvcmVfYWNjZXNzOwoKICAgIGNvbnN0IEludGVnZXIgZGVyZWZlcmVuY2UoKSBjb25zdCB7IHJldHVybiB2YWx1ZV87IH0KCiAgICB2b2lkIGluY3JlbWVudCgpIHsgSU5DUkVNRU5UID8gKyt2YWx1ZV8gOiAtLXZhbHVlXzsgfQoKICAgIGJvb2wgZXF1YWxzKGNvbnN0IGludGVnZXJfaXRlcmF0b3ImIG90aGVyKSBjb25zdCB7IHJldHVybiB2YWx1ZV8gPT0gb3RoZXIudmFsdWVfOyB9CgogICAgSW50ZWdlciB2YWx1ZV87Cn07CgppbnQgbWFpbigpIHsKICAgIHN0ZDo6Y291dCA8PCBzdGQ6OmlzX3NhbWU8aW50ZWdlcl9pdGVyYXRvcjxpbnQ+OjppdGVyYXRvcl9jYXRlZ29yeSwgc3RkOjppbnB1dF9pdGVyYXRvcl90YWc+Ojp2YWx1ZSA8PCBzdGQ6OmVuZGw7CiAgICByZXR1cm4gMDsKfQo=