set_difference.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. // Range v3 library
  2. //
  3. // Copyright Eric Niebler 2014-present
  4. // Copyright Tomislav Ivek 2015-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 <vector>
  13. #include <sstream>
  14. #include <range/v3/core.hpp>
  15. #include <range/v3/range_for.hpp>
  16. #include <range/v3/algorithm/set_algorithm.hpp>
  17. #include <range/v3/algorithm/move.hpp>
  18. #include <range/v3/iterator/operations.hpp>
  19. #include <range/v3/iterator/insert_iterators.hpp>
  20. #include <range/v3/iterator/move_iterators.hpp>
  21. #include <range/v3/functional/identity.hpp>
  22. #include <range/v3/utility/copy.hpp>
  23. #include <range/v3/view/all.hpp>
  24. #include <range/v3/view/const.hpp>
  25. #include <range/v3/view/drop_while.hpp>
  26. #include <range/v3/view/iota.hpp>
  27. #include <range/v3/view/move.hpp>
  28. #include <range/v3/view/reverse.hpp>
  29. #include <range/v3/view/set_algorithm.hpp>
  30. #include <range/v3/view/stride.hpp>
  31. #include <range/v3/view/take.hpp>
  32. #include <range/v3/view/transform.hpp>
  33. #include "../simple_test.hpp"
  34. #include "../test_utils.hpp"
  35. int main()
  36. {
  37. using namespace ranges;
  38. int i1_finite[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
  39. int i2_finite[] = { -3, 2, 4, 4, 6, 9};
  40. auto i1_infinite = views::ints | views::stride(3);
  41. auto i2_infinite = views::ints | views::transform([](int x)
  42. {
  43. return x * x;
  44. });
  45. // difference between two finite ranges/sets
  46. {
  47. auto res = views::set_difference(i1_finite, i2_finite);
  48. CPP_assert(view_<decltype(res)>);
  49. CPP_assert(forward_range<decltype(res)>);
  50. CPP_assert(!random_access_range<decltype(res)>);
  51. CPP_assert(!common_range<decltype(res)>);
  52. using R = decltype(res);
  53. CPP_assert(same_as<range_value_t<R>, int>);
  54. CPP_assert(same_as<range_reference_t<R>, int&>);
  55. CPP_assert(same_as<decltype(iter_move(begin(res))), int &&>);
  56. static_assert(range_cardinality<R>::value == ranges::finite, "Cardinality of difference between two finite ranges should be finite!");
  57. ::check_equal(res, {1, 2, 3, 3, 3, 4, 4});
  58. // check if the final result agrees with the greedy algorithm
  59. std::vector<int> diff;
  60. set_difference(i1_finite, i2_finite, back_inserter(diff));
  61. ::check_equal(res, diff);
  62. CHECK(&*begin(res) == &*(begin(i1_finite)));
  63. }
  64. // difference between two infinite ranges
  65. {
  66. auto res = views::set_difference(i1_infinite, i2_infinite);
  67. CPP_assert(view_<decltype(res)>);
  68. CPP_assert(forward_range<decltype(res)>);
  69. CPP_assert(!random_access_range<decltype(res)>);
  70. CPP_assert(!common_range<decltype(res)>);
  71. using R = decltype(res);
  72. CPP_assert(same_as<range_value_t<R>, int>);
  73. CPP_assert(same_as<range_reference_t<R>, range_reference_t<decltype(i1_infinite)>>);
  74. CPP_assert(same_as<decltype(iter_move(begin(res))), range_rvalue_reference_t<decltype(i1_infinite)>>);
  75. static_assert(range_cardinality<R>::value == ranges::unknown, "Cardinality of difference of infinite ranges should be unknown!");
  76. ::check_equal(res | views::take(5), {3, 6, 12, 15, 18});
  77. // check if the final result agrees with the greedy algorithm
  78. std::vector<int> diff;
  79. set_difference(i1_infinite | views::take(1000), i2_infinite | views::take(1000), back_inserter(diff));
  80. ::check_equal(res | views::take(5), diff | views::take(5));
  81. }
  82. // difference between a finite and an infinite range
  83. {
  84. auto res = views::set_difference(i1_finite, i2_infinite);
  85. CPP_assert(view_<decltype(res)>);
  86. CPP_assert(forward_range<decltype(res)>);
  87. CPP_assert(!random_access_range<decltype(res)>);
  88. CPP_assert(!common_range<decltype(res)>);
  89. using R = decltype(res);
  90. CPP_assert(same_as<range_value_t<R>, int>);
  91. CPP_assert(same_as<range_reference_t<R>, range_reference_t<decltype(i1_finite)>>);
  92. CPP_assert(same_as<decltype(iter_move(begin(res))), range_rvalue_reference_t<decltype(i1_finite)>>);
  93. static_assert(range_cardinality<R>::value == ranges::finite, "Cardinality of difference between a finite range and any other range should be finite!");
  94. ::check_equal(res, {2, 2, 3, 3, 3, 4, 4, 4});
  95. }
  96. // difference between an infinite and a finite range
  97. {
  98. auto res = views::set_difference(i1_infinite, i2_finite);
  99. CPP_assert(view_<decltype(res)>);
  100. CPP_assert(forward_range<decltype(res)>);
  101. CPP_assert(!random_access_range<decltype(res)>);
  102. CPP_assert(!common_range<decltype(res)>);
  103. using R = decltype(res);
  104. CPP_assert(same_as<range_value_t<R>, int>);
  105. CPP_assert(same_as<range_reference_t<R>, range_reference_t<decltype(i1_infinite)>>);
  106. CPP_assert(same_as<range_rvalue_reference_t<R>, range_rvalue_reference_t<decltype(i1_infinite)>>);
  107. static_assert(range_cardinality<R>::value == ranges::infinite, "Cardinality of difference between an infinite and finite range should be infinite!");
  108. ::check_equal(res | views::take(5), {0, 3, 12, 15, 18});
  109. }
  110. // differences involving unknown cardinalities
  111. {
  112. auto rng0 = views::iota(10) | views::drop_while([](int i)
  113. {
  114. return i < 25;
  115. });
  116. static_assert(range_cardinality<decltype(rng0)>::value == ranges::unknown, "");
  117. auto res1 = views::set_difference(i2_finite, rng0);
  118. static_assert(range_cardinality<decltype(res1)>::value == ranges::finite, "Difference between a finite and unknown cardinality set should have finite cardinality!");
  119. auto res2 = views::set_difference(rng0, i2_finite);
  120. static_assert(range_cardinality<decltype(res2)>::value == ranges::unknown, "Difference between an unknown cardinality and finite set should have unknown cardinality!");
  121. auto res3 = views::set_difference(i1_infinite, rng0);
  122. static_assert(range_cardinality<decltype(res3)>::value == ranges::unknown, "Difference between an unknown cardinality and finite set should have unknown cardinality!");
  123. auto res4 = views::set_difference(rng0, i1_infinite);
  124. static_assert(range_cardinality<decltype(res4)>::value == ranges::unknown, "Difference between an unknown and infinite cardinality set should have unknown cardinality!");
  125. }
  126. // test const ranges
  127. {
  128. auto res1 = views::set_difference(views::const_(i1_finite), views::const_(i2_finite));
  129. using R1 = decltype(res1);
  130. CPP_assert(same_as<range_value_t<R1>, int>);
  131. CPP_assert(same_as<range_reference_t<R1>, const int&>);
  132. CPP_assert(same_as<range_rvalue_reference_t<R1>, const int&&>);
  133. auto res2 = views::set_difference(views::const_(i1_finite), i2_finite);
  134. using R2 = decltype(res2);
  135. CPP_assert(same_as<range_value_t<R2>, int>);
  136. CPP_assert(same_as<range_reference_t<R2>, const int&>);
  137. CPP_assert(same_as<range_rvalue_reference_t<R2>, const int&&>);
  138. }
  139. // test different orderings
  140. {
  141. auto res = views::set_difference(views::reverse(i1_finite), views::reverse(i2_finite), [](int a, int b)
  142. {
  143. return a > b;
  144. });
  145. ::check_equal(res, {4, 4, 3, 3, 3, 2, 1});
  146. }
  147. // test projections and sets with different element types
  148. struct S
  149. {
  150. int val;
  151. bool operator==(const S& other) const
  152. {
  153. return val == other.val;
  154. }
  155. };
  156. S s_finite[] = {S{-20}, S{-10}, S{1}, S{3}, S{3}, S{6}, S{8}, S{20}};
  157. {
  158. auto res1 = views::set_difference(s_finite, views::ints(-2, 10),
  159. less(),
  160. &S::val,
  161. identity()
  162. );
  163. using R1 = decltype(res1);
  164. CPP_assert(same_as<range_value_t<R1>, S>);
  165. CPP_assert(same_as<range_reference_t<R1>, S&>);
  166. CPP_assert(same_as<range_rvalue_reference_t<R1>, S&&>);
  167. ::check_equal(res1, {S{-20}, S{-10}, S{3}, S{20}});
  168. auto res2 = views::set_difference(views::ints(-2, 10), s_finite,
  169. less(),
  170. identity(),
  171. [](const S& x){ return x.val; }
  172. );
  173. using R2 = decltype(res2);
  174. CPP_assert(same_as<range_value_t<R2>, int>);
  175. CPP_assert(same_as<range_reference_t<R2>, int>);
  176. CPP_assert(same_as<range_rvalue_reference_t<R2>, int>);
  177. ::check_equal(res2, {-2, -1, 0, 2, 4, 5, 7, 9});
  178. }
  179. // move
  180. {
  181. auto v0 = to<std::vector<MoveOnlyString>>({"a","b","b","c","x","x"});
  182. auto v1 = to<std::vector<MoveOnlyString>>({"b","x","y","z"});
  183. auto res = views::set_difference(v0, v1, [](const MoveOnlyString& a, const MoveOnlyString& b){return a<b;});
  184. std::vector<MoveOnlyString> expected;
  185. move(res, back_inserter(expected));
  186. ::check_equal(expected, {"a","b","c","x"});
  187. ::check_equal(v1, {"b","x","y","z"});
  188. ::check_equal(v0, {"","b","","","x",""});
  189. auto v0_greedy = to<std::vector<MoveOnlyString>>({"a","b","b","c","x","x"});
  190. auto v1_greedy = to<std::vector<MoveOnlyString>>({"b","x","y","z"});
  191. std::vector<MoveOnlyString> expected_greedy;
  192. set_difference(v0_greedy, v1_greedy,
  193. move_into(back_inserter(expected_greedy)),
  194. [](const MoveOnlyString& a, const MoveOnlyString& b){return a<b;});
  195. ::check_equal(expected_greedy, expected);
  196. ::check_equal(v0_greedy, v0);
  197. ::check_equal(v1_greedy, v1);
  198. using R = decltype(res);
  199. CPP_assert(same_as<range_value_t<R>, MoveOnlyString>);
  200. CPP_assert(same_as<range_reference_t<R>, MoveOnlyString &>);
  201. CPP_assert(same_as<range_rvalue_reference_t<R>, MoveOnlyString &&>);
  202. }
  203. // WARNING: set_difference between two infinite ranges can create infinite loops!
  204. // {
  205. // auto empty_range = views::set_difference(views::ints, views::ints);
  206. // begin(empty_range); // infinite loop!
  207. // }
  208. {
  209. auto rng = views::set_difference(
  210. debug_input_view<int const>{i1_finite},
  211. debug_input_view<int const>{i2_finite}
  212. );
  213. ::check_equal(rng, {1, 2, 3, 3, 3, 4, 4});
  214. }
  215. return test_result();
  216. }