fork download
  1. #include <iostream>
  2. #include <iterator>
  3. #include <vector>
  4.  
  5. template <class Derived, class Category, class Value, class Reference = Value&,
  6. class Pointer = Value*, class Distance = std::ptrdiff_t>
  7. class iterator_facade;
  8.  
  9. struct iterator_core_access {
  10. template <class I>
  11. static typename I::reference dereference(const I& i) { return i.dereference(); }
  12.  
  13. template <class I>
  14. static void increment(I& i) { i.increment(); }
  15.  
  16. template <class I>
  17. static void decrement(I& i) { i.decrement(); }
  18.  
  19. template <class I1, class I2>
  20. static bool equal(const I1& i1, const I2& i2) { return i1.equals(i2); }
  21. };
  22.  
  23. namespace detail {
  24.  
  25. template <class Iterator, class Category, class Value, class Reference,
  26. class Pointer, class Distance>
  27. class iterator_facade_base;
  28.  
  29. template <class I, class V, class R, class P, class D>
  30. class iterator_facade_base<I, std::output_iterator_tag, V, R, P, D>
  31. : public std::iterator<std::output_iterator_tag, V, D, P, R> {
  32. public:
  33. R operator * () const { return iterator_core_access::dereference(derived()); }
  34.  
  35. I& operator ++ () {
  36. iterator_core_access::increment(derived());
  37. return derived();
  38. }
  39.  
  40. I operator ++ (int) {
  41. I copy = derived();
  42. ++*this;
  43. return copy;
  44. }
  45.  
  46. protected:
  47. I& derived() { return *static_cast<I*>(this); }
  48.  
  49. const I& derived() const { return *static_cast<const I*>(this); }
  50. };
  51.  
  52. template <class I, class V, class R, class P, class D>
  53. class iterator_facade_base<I, std::input_iterator_tag, V, R, P, D>
  54. : public iterator_facade_base<I, std::output_iterator_tag, V, R, P, D> {
  55. public:
  56. using iterator_category = std::input_iterator_tag;
  57.  
  58. P operator -> () const { return *iterator_core_access::dereference(this->derived()); }
  59. };
  60.  
  61. template <class I, class V, class R, class P, class D>
  62. class iterator_facade_base<I, std::forward_iterator_tag, V, R, P, D>
  63. : public iterator_facade_base<I, std::input_iterator_tag, V, R, P, D> {
  64. public:
  65. using iterator_category = std::forward_iterator_tag;
  66. };
  67.  
  68. template <class I, class V, class R, class P, class D>
  69. class iterator_facade_base<I, std::bidirectional_iterator_tag, V, R, P, D>
  70. : public iterator_facade_base<I, std::forward_iterator_tag, V, R, P, D> {
  71. public:
  72. using iterator_category = std::bidirectional_iterator_tag;
  73.  
  74. I& operator -- () {
  75. iterator_core_access::decrement(this->derived());
  76. return this->derived();
  77. }
  78.  
  79. I operator -- (int) {
  80. I copy = this->derived();
  81. --*this;
  82. return copy;
  83. }
  84. };
  85.  
  86. } // namespace detail
  87.  
  88. template <class I, class C, class V, class R, class P, class D>
  89. class iterator_facade : public detail::iterator_facade_base<I, C, V, R, P, D> {};
  90.  
  91. template <typename Integer, bool INCREMENT = true>
  92. class integer_iterator : public iterator_facade<integer_iterator<Integer, INCREMENT>,
  93. std::input_iterator_tag, Integer, const Integer, Integer*, Integer> {
  94. public:
  95. explicit integer_iterator() : value_() {}
  96.  
  97. explicit integer_iterator(Integer value) : value_(value) {}
  98.  
  99. private:
  100. friend struct iterator_core_access;
  101.  
  102. const Integer dereference() const { return value_; }
  103.  
  104. void increment() { INCREMENT ? ++value_ : --value_; }
  105.  
  106. bool equals(const integer_iterator& other) const { return value_ == other.value_; }
  107.  
  108. Integer value_;
  109. };
  110.  
  111. int main() {
  112. std::cout << std::is_same<integer_iterator<int>::iterator_category, std::input_iterator_tag>::value << std::endl;
  113. return 0;
  114. }
  115.  
Success #stdin #stdout 0s 15240KB
stdin
Standard input is empty
stdout
1