sliding.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // Range v3 library
  2. //
  3. // Copyright Tobias Mayer 2016
  4. // Copyright Casey Carter 2016
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. #include <forward_list>
  13. #include <list>
  14. #include <vector>
  15. #include <range/v3/core.hpp>
  16. #include <range/v3/view/chunk_by.hpp>
  17. #include <range/v3/view/cycle.hpp>
  18. #include <range/v3/view/iota.hpp>
  19. #include <range/v3/view/repeat.hpp>
  20. #include <range/v3/view/repeat_n.hpp>
  21. #include <range/v3/view/reverse.hpp>
  22. #include <range/v3/view/sliding.hpp>
  23. #include <range/v3/view/zip.hpp>
  24. #include "../simple_test.hpp"
  25. #include "../test_utils.hpp"
  26. using namespace ranges;
  27. namespace
  28. {
  29. namespace ebo_test
  30. {
  31. struct empty1 {};
  32. struct empty2 {};
  33. struct refines : empty1, empty2 {};
  34. }
  35. constexpr bool broken_ebo = sizeof(ebo_test::refines) > sizeof(ebo_test::empty1);
  36. constexpr auto N = 7;
  37. constexpr auto K = 3;
  38. CPP_assert(K < N);
  39. template<typename Adapted>
  40. void test_size(Adapted& a, std::true_type)
  41. {
  42. CPP_assert(sized_range<decltype(a)>);
  43. CHECK(size(a), unsigned(N - K + 1));
  44. }
  45. template<typename Adapted>
  46. void test_size(Adapted&, std::false_type)
  47. {}
  48. template<typename Adapted>
  49. void test_common(Adapted& a, std::true_type)
  50. {
  51. CPP_assert(common_range<decltype(a)>);
  52. }
  53. // template<typename Adapted>
  54. // void test_common(Adapted&, std::false_type)
  55. // {}
  56. template<typename Adapted>
  57. void test_prev(Adapted& a, iterator_t<Adapted> const& it, std::true_type)
  58. {
  59. CPP_assert(bidirectional_range<decltype(a)>);
  60. ::check_equal(*ranges::prev(it, 3), views::iota(N - K - 2, N - 2));
  61. }
  62. template<typename Adapted>
  63. void test_prev(Adapted&, iterator_t<Adapted> const&, std::false_type)
  64. {}
  65. template<typename Rng, bool>
  66. struct size_compare_
  67. {
  68. iterator_t<Rng> iter1_;
  69. iterator_t<Rng> iter2_;
  70. range_difference_t<Rng> dist_;
  71. };
  72. template<typename Rng>
  73. struct size_compare_<Rng, true>
  74. {
  75. iterator_t<Rng> iter1_;
  76. range_difference_t<Rng> dist_;
  77. };
  78. template<typename Rng>
  79. using size_compare =
  80. size_compare_<Rng, random_access_range<Rng> || (bidirectional_range<Rng> && common_range<Rng>)>;
  81. template<typename ToBase>
  82. void test_finite(ToBase to_base)
  83. {
  84. auto v = to_base(views::iota(0,N));
  85. using Base = decltype(v);
  86. auto rng = v | views::sliding(K);
  87. using Adapted = decltype(rng);
  88. test_size(rng, meta::bool_<sized_range<Base>>{});
  89. using IterTagOfBase =
  90. meta::if_c<contiguous_iterator<iterator_t<Base>>,
  91. std::random_access_iterator_tag,
  92. iterator_tag_of<iterator_t<Base>>>;
  93. CPP_assert(same_as<
  94. IterTagOfBase,
  95. iterator_tag_of<iterator_t<Adapted>>>);
  96. auto it = ranges::begin(rng);
  97. test_common(rng, meta::bool_<common_range<Base>>{});
  98. for (auto i = 0; i <= N - K; ++i)
  99. {
  100. ::check_equal(*it++, views::iota(i, i + K));
  101. }
  102. CHECK(it == ranges::end(rng));
  103. test_prev(rng, it, meta::bool_<bidirectional_range<Base>>{});
  104. if (!broken_ebo)
  105. {
  106. CHECK(sizeof(it) == sizeof(size_compare<Base>));
  107. }
  108. }
  109. }
  110. void bug_975()
  111. {
  112. std::vector<double> v{2.0, 2.0, 3.0, 1.0};
  113. std::vector<int> i{1, 2, 1, 2};
  114. std::vector<int> t{1, 1, 2, 2};
  115. {
  116. using namespace ranges;
  117. auto vals = views::zip(v, i, t);
  118. using T = std::tuple<double, int, int>;
  119. auto g = vals | views::chunk_by(
  120. [](T t1, T t2)
  121. {
  122. return std::get<2>(t1) == std::get<2>(t2);
  123. }
  124. );
  125. auto windows = views::sliding(g, 2);
  126. auto it = std::begin(windows);
  127. (void)it;
  128. }
  129. }
  130. int main()
  131. {
  132. test_finite(to<std::forward_list<int>>());
  133. test_finite(to<std::list<int>>());
  134. test_finite(to<std::vector<int>>());
  135. test_finite(identity{});
  136. {
  137. // An infinite, cyclic range with cycle length == 1
  138. auto rng = views::repeat(5) | views::sliding(K);
  139. CPP_assert(random_access_range<decltype(rng)>);
  140. auto it = rng.begin();
  141. CPP_assert(random_access_iterator<decltype(it)>);
  142. #if defined(__GNUC__) && !defined(__clang__) && \
  143. ((__GNUC__ == 6 && __GNUC_MINOR__ < 3) || __GNUC__ < 6)
  144. // Avoid https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78047
  145. {
  146. auto deref = *it;
  147. auto i = deref.begin();
  148. for (auto n = 0; n < K; ++n) {
  149. RANGES_ENSURE(i != deref.end());
  150. CHECK(*i == 5);
  151. ++i;
  152. }
  153. CHECK(i == deref.end());
  154. }
  155. auto it2 = next(it, 42);
  156. CHECK(it != it2);
  157. {
  158. auto deref = *it;
  159. auto i = deref.begin();
  160. for (auto n = 0; n < K; ++n) {
  161. RANGES_ENSURE(i != deref.end());
  162. CHECK(*i == 5);
  163. ++i;
  164. }
  165. CHECK(i == deref.end());
  166. }
  167. #else
  168. ::check_equal(*it, views::repeat_n(5, K));
  169. auto it2 = next(it, 42);
  170. CHECK(it != it2);
  171. ::check_equal(*it2, views::repeat_n(5, K));
  172. #endif
  173. }
  174. {
  175. // An infinite, cyclic range with cycle length == K
  176. auto rng = views::iota(0, K) | views::cycle | views::sliding(K);
  177. CPP_assert(random_access_range<decltype(rng)>);
  178. auto it = rng.begin();
  179. CPP_assert(random_access_iterator<decltype(it)>);
  180. for (auto i = 0; i < 42; ++i)
  181. {
  182. ::check_equal(*it++, {0,1,2});
  183. ::check_equal(*it++, {1,2,0});
  184. ::check_equal(*it++, {2,0,1});
  185. }
  186. auto it2 = next(it, 42 * K);
  187. ::check_equal(*it2, {0,1,2});
  188. }
  189. {
  190. // An infinite, cyclic range with cycle length > K
  191. auto rng = views::iota(0,7) | views::cycle | views::sliding(K);
  192. //[0,1,2],[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,0],[6,0,1],...
  193. auto it = rng.begin();
  194. CPP_assert(random_access_iterator<decltype(it)>);
  195. ::check_equal(*it, {0,1,2});
  196. ::check_equal(*next(it, 2), {2,3,4});
  197. ::check_equal(*next(it,16), {2,3,4});
  198. ::check_equal(*next(it,27), {6,0,1});
  199. }
  200. return ::test_result();
  201. }