chunk.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // Range v3 library
  2. //
  3. // Copyright Eric Niebler 2014-present
  4. //
  5. // Use, modification and distribution is subject to the
  6. // Boost Software License, Version 1.0. (See accompanying
  7. // file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // Project home: https://github.com/ericniebler/range-v3
  11. #include <iostream>
  12. #include <forward_list>
  13. #include <list>
  14. #include <vector>
  15. #include <range/v3/range/conversion.hpp>
  16. #include <range/v3/view/chunk.hpp>
  17. #include <range/v3/view/cycle.hpp>
  18. #include <range/v3/view/filter.hpp>
  19. #include <range/v3/view/iota.hpp>
  20. #include <range/v3/view/join.hpp>
  21. #include <range/v3/view/move.hpp>
  22. #include <range/v3/view/repeat.hpp>
  23. #include <range/v3/view/reverse.hpp>
  24. #include "../simple_test.hpp"
  25. #include "../test_iterators.hpp"
  26. #include "../test_utils.hpp"
  27. using namespace ranges;
  28. namespace
  29. {
  30. void test_input_ranges()
  31. {
  32. int const ints[] = {0,1,2,3,4};
  33. static constexpr auto N = ranges::size(ints);
  34. static constexpr auto K = 2;
  35. auto make_range = [&]{ return debug_input_view<int const>{ints} | views::chunk(K); };
  36. auto rng = make_range();
  37. using Rng = decltype(rng);
  38. CPP_assert(input_range<Rng>);
  39. CPP_assert(view_<Rng>);
  40. CPP_assert(!forward_range<Rng>);
  41. CPP_assert(sized_range<Rng>);
  42. CHECK(ranges::size(rng) == (N + K - 1) / K);
  43. CPP_assert(sized_sentinel_for<sentinel_t<Rng>, iterator_t<Rng>>);
  44. CHECK((ranges::end(rng) - ranges::begin(rng)) == int((N + K - 1) / K));
  45. rng = make_range();
  46. auto i = ranges::begin(rng);
  47. auto e = ranges::end(rng);
  48. CHECK(i != e);
  49. if (i == e) return;
  50. {
  51. auto r = *i;
  52. CHECK(ranges::size(r) == 2u);
  53. auto ii = ranges::begin(r);
  54. auto ee = ranges::end(r);
  55. CHECK(ii != ee);
  56. if (ii == ee) return;
  57. CHECK((ee - ii) == 2);
  58. CHECK(*ii == 0);
  59. CHECK(++ii != ee);
  60. if (ii == ee) return;
  61. CHECK((ee - ii) == 1);
  62. CHECK(*ii == 1);
  63. CHECK(++ii == ee);
  64. CHECK((ee - ii) == 0);
  65. }
  66. CHECK(++i != e);
  67. if (i == e) return;
  68. ::check_equal(*i, {2,3});
  69. CHECK(++i != e);
  70. if (i != e)
  71. {
  72. ::check_equal(*i, {4});
  73. CHECK(++i == e);
  74. }
  75. }
  76. }
  77. int main()
  78. {
  79. {
  80. auto v = views::iota(0,11) | to<std::vector>();
  81. auto rng1 = v | views::chunk(3);
  82. CPP_assert(random_access_range<decltype(rng1)>);
  83. CPP_assert(sized_range<decltype(rng1)>);
  84. auto it1 = ranges::begin(rng1);
  85. ::check_equal(*it1++, {0,1,2});
  86. ::check_equal(*it1++, {3,4,5});
  87. ::check_equal(*it1++, {6,7,8});
  88. ::check_equal(*it1++, {9,10});
  89. CHECK(it1 == ranges::end(rng1));
  90. ::check_equal(*ranges::next(it1, -3), {3,4,5});
  91. CHECK(size(rng1), 4u);
  92. CHECK(sizeof(rng1.begin()) == sizeof(v.begin()) * 2 + sizeof(std::ptrdiff_t) * 2);
  93. }
  94. {
  95. auto l = views::iota(0,11) | to<std::forward_list>();
  96. auto rng2 = l | views::chunk(3);
  97. CPP_assert(forward_range<decltype(rng2)>);
  98. CPP_assert(!bidirectional_range<decltype(rng2)>);
  99. CPP_assert(!sized_range<decltype(rng2)>);
  100. auto it2 = ranges::begin(rng2);
  101. ::check_equal(*it2++, {0,1,2});
  102. ::check_equal(*it2++, {3,4,5});
  103. ::check_equal(*it2++, {6,7,8});
  104. ::check_equal(*it2++, {9,10});
  105. CHECK(it2 == ranges::end(rng2));
  106. CHECK(sizeof(rng2.begin()) == sizeof(l.begin()) * 2 + sizeof(std::ptrdiff_t));
  107. }
  108. {
  109. // An infinite, cyclic range with cycle length == 1
  110. auto fives = views::repeat(5);
  111. CPP_assert(random_access_range<decltype(fives)>);
  112. auto rng = fives | views::chunk(3);
  113. CPP_assert(random_access_range<decltype(rng)>);
  114. auto it = rng.begin();
  115. auto it2 = next(it,3);
  116. CHECK((it2 - it) == 3);
  117. ::check_equal(*it, {5,5,5});
  118. ::check_equal(*it2, {5,5,5});
  119. }
  120. {
  121. // An infinite, cyclic range with cycle length == 3
  122. int const ints[] = {0,1,2};
  123. auto cyc = ints | views::cycle;
  124. //[0,1],[2,0],[1,2],[0,1],[2,0],[1,2],
  125. auto rng = cyc | views::chunk(2);
  126. CPP_assert(random_access_range<decltype(rng)>);
  127. auto it = rng.begin();
  128. auto it2 = next(it,2);
  129. ::check_equal(*it, {0,1});
  130. ::check_equal(*it2, {1,2});
  131. CHECK((it - it) == 0);
  132. CHECK((next(it,1) - it) == 1);
  133. CHECK((next(it,2) - it) == 2);
  134. CHECK((next(it,3) - it) == 3);
  135. CHECK((next(it,4) - it) == 4);
  136. CHECK((next(it,5) - it) == 5);
  137. CHECK((next(it,6) - it) == 6);
  138. CHECK((next(it,7) - it) == 7 );
  139. }
  140. {
  141. // An infinite, cyclic range with cycle length == 3
  142. int const ints[] = {0,1,2};
  143. auto cyc = ints | views::cycle;
  144. //[0,1,2,0],[1,2,0,1],[2,0,1,2],...
  145. auto rng = cyc | views::chunk(4);
  146. CPP_assert(random_access_range<decltype(rng)>);
  147. auto it = rng.begin();
  148. auto it2 = next(it,2);
  149. ::check_equal(*it, {0,1,2,0});
  150. ::check_equal(*it2, {2,0,1,2});
  151. // Strange, but not wrong necessarily:
  152. CHECK((it - it) == 0);
  153. CHECK((next(it,1) - it) == 1);
  154. CHECK((next(it,2) - it) == 2);
  155. CHECK((next(it,3) - it) == 3);
  156. CHECK((next(it,4) - it) == 4);
  157. CHECK((next(it,5) - it) == 5);
  158. CHECK((next(it,6) - it) == 6);
  159. CHECK((next(it,7) - it) == 7);
  160. }
  161. {
  162. // An infinite, cyclic range with cycle length == 10
  163. int const ints[] = {0,1,2,3,4,5,6,7,8,9};
  164. auto cyc = ints | views::cycle;
  165. auto rng = cyc | views::chunk(3);
  166. CPP_assert(random_access_range<decltype(rng)>);
  167. //[0,1,2],[3,4,5],[6,7,8],[9,0,1],[2,3,4],...
  168. auto it = rng.begin();
  169. auto it2 = next(it,2);
  170. ::check_equal(*it, {0,1,2});
  171. ::check_equal(*it2, {6,7,8});
  172. // Strange, but not wrong necessarily:
  173. CHECK((it - it) == 0);
  174. CHECK((next(it,1) - it) == 1);
  175. CHECK((next(it,2) - it) == 2);
  176. CHECK((next(it,3) - it) == 3);
  177. CHECK((next(it,4) - it) == 4);
  178. CHECK((next(it,5) - it) == 5);
  179. CHECK((next(it,6) - it) == 6);
  180. CHECK((next(it,7) - it) == 7);
  181. CHECK((next(it,8) - it) == 8);
  182. CHECK((next(it,9) - it) == 9);
  183. CHECK((next(it,10) - it) == 10);
  184. CHECK((next(it,11) - it) == 11);
  185. CHECK((next(it,12) - it) == 12);
  186. CHECK((next(it,13) - it) == 13);
  187. }
  188. test_input_ranges();
  189. {
  190. // Regression test for #567
  191. std::vector<std::vector<int>> vec{{1, 2, 3}, {4, 5, 6}};
  192. auto rng = vec | views::join | views::chunk(2);
  193. CPP_assert(input_range<decltype(rng)>);
  194. CPP_assert(input_range<range_reference_t<decltype(rng)>>);
  195. int const expected[][2] = {{1, 2}, {3, 4}, {5, 6}};
  196. ::check_equal(rng, expected);
  197. }
  198. {
  199. // Regression test for not-exactly #567 (https://github.com/ericniebler/range-v3/issues/567#issuecomment-315148392)
  200. int some_ints[] = {0,1,2,3};
  201. int const expected[][2] = {{0, 1}, {2, 3}};
  202. auto rng = views::all(some_ints);
  203. ::check_equal(rng | views::chunk(2), expected);
  204. }
  205. {
  206. // Regression test for https://stackoverflow.com/questions/49210190
  207. auto rng = views::closed_iota(1,25)
  208. | views::filter([](int item){ return item % 10 != 0; })
  209. | views::chunk(10);
  210. auto it = ranges::begin(rng);
  211. auto last = ranges::end(rng);
  212. CHECK(it != last);
  213. ::check_equal(*it, {1,2,3,4,5,6,7,8,9,11});
  214. CHECK(++it != last);
  215. ::check_equal(*it, {12,13,14,15,16,17,18,19,21,22});
  216. CHECK(++it != last);
  217. ::check_equal(*it, {23,24,25});
  218. CHECK(++it == last);
  219. }
  220. return ::test_result();
  221. }