remove_if.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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 <array>
  12. #include <vector>
  13. #include <iterator>
  14. #include <functional>
  15. #include <range/v3/core.hpp>
  16. #include <range/v3/functional/not_fn.hpp>
  17. #include <range/v3/view/remove_if.hpp>
  18. #include <range/v3/view/filter.hpp>
  19. #include <range/v3/view/counted.hpp>
  20. #include <range/v3/view/concat.hpp>
  21. #include <range/v3/view/reverse.hpp>
  22. #include <range/v3/view/subrange.hpp>
  23. #include <range/v3/utility/copy.hpp>
  24. #include "../simple_test.hpp"
  25. #include "../test_utils.hpp"
  26. #include "../test_iterators.hpp"
  27. struct is_odd
  28. {
  29. constexpr bool operator()(int i) const
  30. {
  31. return (i % 2) == 1;
  32. }
  33. };
  34. struct is_even
  35. {
  36. constexpr bool operator()(int i) const
  37. {
  38. return (i % 2) == 0;
  39. }
  40. };
  41. struct my_data
  42. {
  43. int i;
  44. };
  45. constexpr bool operator==(my_data left, my_data right)
  46. {
  47. return left.i == right.i;
  48. }
  49. int main()
  50. {
  51. using namespace ranges;
  52. int rgi[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  53. {
  54. auto rng = rgi | views::remove_if(is_even());
  55. has_type<int &>(*begin(rgi));
  56. has_type<int &>(*begin(rng));
  57. CPP_assert(view_<decltype(rng)>);
  58. CPP_assert(common_range<decltype(rng)>);
  59. CPP_assert(!sized_range<decltype(rng)>);
  60. CPP_assert(bidirectional_range<decltype(rng)>);
  61. CPP_assert(!random_access_range<decltype(rng)>);
  62. ::check_equal(rng, {1,3,5,7,9});
  63. ::check_equal(rng | views::reverse, {9,7,5,3,1});
  64. auto tmp = rng | views::reverse;
  65. CHECK(&*begin(tmp) == &rgi[8]);
  66. }
  67. {
  68. auto rng2 = views::counted(rgi, 10) | views::remove_if(not_fn(is_odd()));
  69. has_type<int &>(*begin(rng2));
  70. CPP_assert(view_<decltype(rng2)>);
  71. CPP_assert(bidirectional_range<decltype(rng2)>);
  72. CPP_assert(!random_access_range<decltype(rng2)>);
  73. CPP_assert(common_range<decltype(rng2)>);
  74. CPP_assert(!sized_range<decltype(rng2)>);
  75. ::check_equal(rng2, {1,3,5,7,9});
  76. CHECK(&*begin(rng2) == &rgi[0]);
  77. }
  78. {
  79. auto rng3 = views::counted(BidirectionalIterator<int*>{rgi}, 10) | views::remove_if(is_even());
  80. has_type<int &>(*begin(rng3));
  81. CPP_assert(view_<decltype(rng3)>);
  82. CPP_assert(bidirectional_range<decltype(rng3)>);
  83. CPP_assert(!random_access_range<decltype(rng3)>);
  84. CPP_assert(!common_range<decltype(rng3)>);
  85. CPP_assert(!sized_range<decltype(rng3)>);
  86. ::check_equal(rng3, {1,3,5,7,9});
  87. CHECK(&*begin(rng3) == &rgi[0]);
  88. CHECK(&*prev(next(begin(rng3))) == &rgi[0]);
  89. }
  90. {
  91. // Test remove_if with a mutable lambda
  92. bool flag = true;
  93. auto mutable_rng = views::remove_if(rgi, [flag](int) mutable { return flag = !flag;});
  94. ::check_equal(mutable_rng, {1,3,5,7,9});
  95. CPP_assert(view_<decltype(mutable_rng)>);
  96. CPP_assert(!view_<decltype(mutable_rng) const>);
  97. }
  98. {
  99. const std::array<int, 3> a{{0, 1, 2}};
  100. const std::vector<int> b{3, 4, 5, 6};
  101. auto r = views::concat(a, b);
  102. auto f = [](int i) { return i != 1 && i != 5; };
  103. auto r2 = r | views::remove_if(f);
  104. ::check_equal(r2, {1,5});
  105. }
  106. {
  107. auto rng = debug_input_view<int const>{rgi} | views::remove_if(is_even{});
  108. ::check_equal(rng, {1,3,5,7,9});
  109. }
  110. {
  111. // Defend against regression of #793
  112. int const some_ints[] = {1, 2, 3};
  113. auto a = some_ints | ranges::views::remove_if([](int val) { return val > 0; });
  114. CHECK(a.empty());
  115. }
  116. {
  117. // with projection
  118. const std::vector<my_data> some_my_datas{{1}, {2}, {3}, {4}};
  119. {
  120. // views::remove_if without pipe
  121. auto rng = ranges::views::remove_if(some_my_datas, is_even(), &my_data::i);
  122. ::check_equal(rng, std::vector<my_data>{{1}, {3}});
  123. }
  124. {
  125. // views::remove_if with pipe
  126. auto rng = some_my_datas | ranges::views::remove_if(is_even(), &my_data::i);
  127. ::check_equal(rng, std::vector<my_data>{{1}, {3}});
  128. }
  129. {
  130. // views::filter without pipe
  131. auto rng = ranges::views::filter(some_my_datas, is_even(), &my_data::i);
  132. ::check_equal(rng, std::vector<my_data>{{2}, {4}});
  133. }
  134. {
  135. // views::filter with pipe
  136. auto rng = some_my_datas | ranges::views::filter(is_even(), &my_data::i);
  137. ::check_equal(rng, std::vector<my_data>{{2}, {4}});
  138. }
  139. }
  140. // test constexpr binding
  141. {
  142. using namespace ranges;
  143. constexpr std::array<int, 4> is = {{1,2,3,4}};
  144. constexpr auto filter = views::remove_if(is_even()) | views::remove_if(is_odd());
  145. auto rng = is | filter;
  146. CHECK(rng.empty());
  147. }
  148. {
  149. const std::vector<my_data> some_my_datas{{1}, {2}, {3}, {4}};
  150. constexpr auto filter = views::remove_if(is_even(), &my_data::i) | views::remove_if(is_odd(), &my_data::i);
  151. auto rng = some_my_datas | filter;
  152. CHECK(rng.empty());
  153. }
  154. // test issue #1424 <https://github.com/ericniebler/range-v3/issues/1424>
  155. {
  156. std::vector<int> v{1, 2, 3, 4};
  157. auto rng = views::filter(v, is_odd());
  158. ::check_equal(rng, {1, 3});
  159. }
  160. return test_result();
  161. }