fork download
  1. #include <array>
  2. #include <cstddef>
  3. #include <memory>
  4. #include <tuple>
  5.  
  6. namespace detail {
  7. template<std::size_t, typename>
  8. class slide_iterator;
  9. }
  10. template<std::size_t N, typename I>
  11. detail::slide_iterator<N, I> slide_begin(const I&);
  12. template<std::size_t N, typename I>
  13. detail::slide_iterator<N, I> slide_end(const I&);
  14.  
  15. namespace detail {
  16.  
  17. template<std::size_t N, typename T, typename... Args>
  18. struct repeat {
  19. typedef typename repeat<N - 1, T, T, Args...>::type type;
  20. template<typename I>
  21. type operator()(const I& it, Args&... args) const {
  22. auto jt = it;
  23. return repeat<N - 1, T, T, Args...>()(++jt, args..., *it);
  24. }
  25. };
  26. template<typename T, typename... Args>
  27. struct repeat<0, T, Args...> {
  28. typedef std::tuple<Args&...> type;
  29. template<typename I>
  30. type operator()(const I&, Args&... args) const {
  31. return type(args...);
  32. }
  33. };
  34.  
  35. template<std::size_t N, typename I /* forward iterator */>
  36. class slide_iterator {
  37. public:
  38.  
  39. typedef slide_iterator iterator;
  40. typedef decltype(*I{}) reference;
  41. typedef typename repeat<N, reference>::type window_tuple;
  42.  
  43. slide_iterator()
  44. : dirty_(true) {}
  45. ~slide_iterator() = default;
  46. slide_iterator(const iterator& it)
  47. : first_(it.first_), last_(it.last_), dirty_(true) {}
  48.  
  49. iterator& operator=(const iterator& it) {
  50. first_ = it.first_;
  51. last_ = it.last_;
  52. dirty_ = true;
  53. window_.reset(nullptr);
  54. }
  55.  
  56. const window_tuple& operator*() const {
  57. evaluate();
  58. return *window_;
  59. }
  60.  
  61. const window_tuple* operator->() const {
  62. evaluate();
  63. return window_.get();
  64. }
  65.  
  66. iterator& operator++() { // prefix
  67. ++first_;
  68. ++last_;
  69. dirty_ = true;
  70. return *this;
  71. }
  72.  
  73. iterator operator++(int) { // postfix
  74. auto tmp{*this};
  75. operator++();
  76. return tmp;
  77. }
  78.  
  79. friend void swap(iterator& lhs, iterator& rhs) {
  80. swap(lhs.first_, rhs.first_);
  81. swap(lhs.last_, rhs.last_);
  82. swap(lhs.dirty_, rhs.dirty_);
  83. swap(lhs.window_, rhs.window_);
  84. }
  85.  
  86. friend bool operator==(const iterator& lhs, const iterator& rhs) {
  87. return lhs.last_ == rhs.last_;
  88. }
  89.  
  90. friend bool operator!=(const iterator& lhs, const iterator& rhs) {
  91. return !operator==(lhs, rhs);
  92. }
  93.  
  94. friend iterator slide_begin<N, I>(const I& it);
  95. friend iterator slide_end<N, I>(const I& it);
  96.  
  97. private:
  98.  
  99. void evaluate() const {
  100. if (!dirty_) {
  101. return;
  102. }
  103. dirty_ = false;
  104. window_.reset(new window_tuple(repeat<N, reference>()(first_)));
  105. }
  106.  
  107. I first_;
  108. I last_; // for equality only
  109. mutable bool dirty_; // lazy evaluation
  110. mutable std::unique_ptr<window_tuple> window_;
  111.  
  112. };
  113.  
  114. template<typename T, std::size_t N>
  115. struct slide_helper {
  116. T& t;
  117. auto begin() -> decltype(slide_begin<N>(t.begin())) {
  118. return slide_begin<N>(t.begin());
  119. }
  120. auto end() -> decltype(slide_end<N>(t.end())) {
  121. return slide_end<N>(t.end());
  122. }
  123. };
  124.  
  125. } // ::detail
  126.  
  127. // note it is undefined to call slide_begin<N>() on an iterator which cannot
  128. // be incremented at least N - 1 times
  129. template<std::size_t N, typename I>
  130. detail::slide_iterator<N, I> slide_begin(const I& it) {
  131. detail::slide_iterator<N, I> r;
  132. r.first_ = r.last_ = it;
  133. std::advance(r.last_, N - 1);
  134. return r;
  135. }
  136.  
  137. template<std::size_t N, typename I>
  138. detail::slide_iterator<N, I> slide_end(const I& it) {
  139. detail::slide_iterator<N, I> r;
  140. r.last_ = it;
  141. return r;
  142. }
  143.  
  144. template<std::size_t N, typename T>
  145. detail::slide_helper<T, N> slide(T& t) {
  146. return {t};
  147. }
  148.  
  149. // example usage
  150. #include <iostream>
  151. #include <vector>
  152.  
  153. int main() {
  154. std::vector<int> v{1, 2, 3, 4};
  155. /* helper for
  156.   for (auto it = slide_begin<2>(v.begin()),
  157.   et = slide_end<2>(v.end()); it != et ... BLAH BLAH BLAH */
  158. for (const auto& t : slide<2>(v)) {
  159. std::get<1>(t) *= std::get<0>(t);
  160. }
  161. for (const auto& i : v) {
  162. std::cout << i << std::endl;
  163. }
  164. }
Success #stdin #stdout 0s 3428KB
stdin
Standard input is empty
stdout
1
2
6
24