fork download
  1. #include <cassert>
  2.  
  3. #include <iostream>
  4. #include <iterator>
  5. #include <vector>
  6.  
  7. template <typename C>
  8. struct iterator { using type = typename C::iterator; };
  9.  
  10. template <typename C>
  11. struct iterator<C const> { using type = typename C::const_iterator; };
  12.  
  13. template <typename C>
  14. class ForwardRange {
  15. using Iter = typename iterator<C>::type;
  16. public:
  17. using pointer = typename std::iterator_traits<Iter>::pointer;
  18. using reference = typename std::iterator_traits<Iter>::reference;
  19. using value_type = typename std::iterator_traits<Iter>::value_type;
  20.  
  21. ForwardRange(): _begin(), _end() {}
  22.  
  23. explicit ForwardRange(C& c): _begin(begin(c)), _end(end(c)) {}
  24.  
  25. // Observers
  26. explicit operator bool() const { return _begin != _end; }
  27.  
  28. reference operator*() const { assert(*this); return *_begin; }
  29. pointer operator->() const { assert(*this); return &*_begin; }
  30.  
  31. // Modifiers
  32. ForwardRange& operator++() { assert(*this); ++_begin; return *this; }
  33. ForwardRange operator++(int) { ForwardRange tmp(*this); ++*this; return tmp; }
  34.  
  35. private:
  36. Iter _begin;
  37. Iter _end;
  38. }; // class ForwardRange
  39.  
  40. template <typename C, size_t N>
  41. class FlattenedForwardRange {
  42. using Iter = typename iterator<C>::type;
  43. using Inner = FlattenedForwardRange<typename std::iterator_traits<Iter>::value_type, N-1>;
  44. public:
  45. using pointer = typename Inner::pointer;
  46. using reference = typename Inner::reference;
  47. using value_type = typename Inner::value_type;
  48.  
  49. FlattenedForwardRange(): _outer(), _inner() {}
  50.  
  51. explicit FlattenedForwardRange(C& outer): _outer(outer), _inner() {
  52. if (not _outer) { return; }
  53. _inner = Inner{*_outer};
  54. this->advance();
  55. }
  56.  
  57. // Observers
  58. explicit operator bool() const { return static_cast<bool>(_outer); }
  59.  
  60. reference operator*() const { assert(*this); return *_inner; }
  61. pointer operator->() const { assert(*this); return _inner.operator->(); }
  62.  
  63. // Modifiers
  64. FlattenedForwardRange& operator++() { ++_inner; this->advance(); return *this; }
  65. FlattenedForwardRange operator++(int) { FlattenedForwardRange tmp(*this); ++*this; return tmp; }
  66.  
  67. private:
  68. void advance() {
  69. if (_inner) { return; }
  70.  
  71. for (++_outer; _outer; ++_outer) {
  72. _inner = Inner{*_outer};
  73. if (_inner) { return; }
  74. }
  75. _inner = Inner{};
  76. }
  77.  
  78. ForwardRange<C> _outer;
  79. Inner _inner;
  80. }; // class FlattenedForwardRange
  81.  
  82. template <typename C>
  83. class FlattenedForwardRange<C, 0> {
  84. using Iter = typename iterator<C>::type;
  85. public:
  86. using pointer = typename std::iterator_traits<Iter>::pointer;
  87. using reference = typename std::iterator_traits<Iter>::reference;
  88. using value_type = typename std::iterator_traits<Iter>::value_type;
  89.  
  90. FlattenedForwardRange(): _range() {}
  91.  
  92. explicit FlattenedForwardRange(C& c): _range(c) {}
  93.  
  94. // Observers
  95. explicit operator bool() const { return static_cast<bool>(_range); }
  96.  
  97. reference operator*() const { return *_range; }
  98. pointer operator->() const { return _range.operator->(); }
  99.  
  100. // Modifiers
  101. FlattenedForwardRange& operator++() { ++_range; return *this; }
  102. FlattenedForwardRange operator++(int) { FlattenedForwardRange tmp(*this); ++*this; return tmp; }
  103.  
  104. private:
  105. ForwardRange<C> _range;
  106. }; // class FlattenedForwardRange
  107.  
  108. int main() {
  109. // Forward Range test
  110. std::vector<int> vec{ 1, 2, 3, 4 };
  111. for (ForwardRange<std::vector<int>> fr(vec); fr; ++fr) { std::cout << *fr << "\n"; }
  112.  
  113. // Flattened Forward Range test
  114. std::vector<std::vector<int>> vecvec{ { 1, 2, 3, 4 }, {}, { 5, 6 } };
  115. for (FlattenedForwardRange<std::vector<std::vector<int>>, 1> ffr(vecvec); ffr; ++ffr) {
  116. std::cout << *ffr << "\n";
  117. }
  118. return 0;
  119. }
Success #stdin #stdout 0.01s 5292KB
stdin
Standard input is empty
stdout
1
2
3
4
1
2
3
4
5
6