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() = default;
  44. ~slide_iterator() = default;
  45. slide_iterator(const iterator& it) = default;
  46. iterator& operator=(const iterator& it) = default;
  47.  
  48. window_tuple operator*() const {
  49. return repeat<N, reference>()(first_);
  50. }
  51.  
  52. iterator& operator++() { // prefix
  53. ++first_;
  54. ++last_;
  55. return *this;
  56. }
  57.  
  58. iterator operator++(int) { // postfix
  59. auto tmp{*this};
  60. operator++();
  61. return tmp;
  62. }
  63.  
  64. friend void swap(iterator& lhs, iterator& rhs) {
  65. swap(lhs.first_, rhs.first_);
  66. swap(lhs.last_, rhs.last_);
  67. swap(lhs.dirty_, rhs.dirty_);
  68. swap(lhs.window_, rhs.window_);
  69. }
  70.  
  71. friend bool operator==(const iterator& lhs, const iterator& rhs) {
  72. return lhs.last_ == rhs.last_;
  73. }
  74.  
  75. friend bool operator!=(const iterator& lhs, const iterator& rhs) {
  76. return !operator==(lhs, rhs);
  77. }
  78.  
  79. friend iterator slide_begin<N, I>(const I& it);
  80. friend iterator slide_end<N, I>(const I& it);
  81.  
  82. private:
  83.  
  84. I first_;
  85. I last_; // for equality only
  86.  
  87. };
  88.  
  89. template<typename T, std::size_t N>
  90. struct slide_helper {
  91. T& t;
  92. auto begin() -> decltype(slide_begin<N>(t.begin())) {
  93. return slide_begin<N>(t.begin());
  94. }
  95. auto end() -> decltype(slide_end<N>(t.end())) {
  96. return slide_end<N>(t.end());
  97. }
  98. };
  99.  
  100. } // ::detail
  101.  
  102. // note it is undefined to call slide_begin<N>() on an iterator which cannot
  103. // be incremented at least N - 1 times
  104. template<std::size_t N, typename I>
  105. detail::slide_iterator<N, I> slide_begin(const I& it) {
  106. detail::slide_iterator<N, I> r;
  107. r.first_ = r.last_ = it;
  108. std::advance(r.last_, N - 1);
  109. return r;
  110. }
  111.  
  112. template<std::size_t N, typename I>
  113. detail::slide_iterator<N, I> slide_end(const I& it) {
  114. detail::slide_iterator<N, I> r;
  115. r.last_ = it;
  116. return r;
  117. }
  118.  
  119. template<std::size_t N, typename T>
  120. detail::slide_helper<T, N> slide(T& t) {
  121. return {t};
  122. }
  123.  
  124. // example usage
  125. #include <iostream>
  126. #include <vector>
  127.  
  128. int main() {
  129. std::vector<int> v{1, 2, 3, 4};
  130. for (const auto& t : slide<2>(v)) {
  131. std::get<1>(t) *= std::get<0>(t);
  132. }
  133. for (const auto& i : v) {
  134. std::cerr << i << std::endl;
  135. }
  136. }
Success #stdin #stdout #stderr 0s 3472KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
1
2
6
24