unique.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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 <cctype>
  12. #include <string>
  13. #include <vector>
  14. #include <range/v3/core.hpp>
  15. #include <range/v3/algorithm/copy.hpp>
  16. #include <range/v3/view/delimit.hpp>
  17. #include <range/v3/view/reverse.hpp>
  18. #include <range/v3/view/transform.hpp>
  19. #include <range/v3/view/unique.hpp>
  20. #include <range/v3/utility/copy.hpp>
  21. #include <range/v3/iterator/operations.hpp>
  22. #include <range/v3/iterator/insert_iterators.hpp>
  23. #include "../simple_test.hpp"
  24. #include "../test_utils.hpp"
  25. using std::toupper;
  26. // from http://stackoverflow.com/a/2886589/195873
  27. struct ci_char_traits : std::char_traits<char>
  28. {
  29. static bool eq(char c1, char c2) { return toupper(c1) == toupper(c2); }
  30. static bool ne(char c1, char c2) { return toupper(c1) != toupper(c2); }
  31. static bool lt(char c1, char c2) { return toupper(c1) < toupper(c2); }
  32. static int compare(const char* s1, const char* s2, std::size_t n)
  33. {
  34. for(; n != 0; ++s1, ++s2, --n)
  35. {
  36. if(toupper(*s1) < toupper(*s2))
  37. return -1;
  38. if(toupper(*s1) > toupper(*s2))
  39. return 1;
  40. }
  41. return 0;
  42. }
  43. static const char* find(const char* s, int n, char a)
  44. {
  45. for(; n-- > 0; ++s)
  46. if(toupper(*s) == toupper(a))
  47. break;
  48. return s;
  49. }
  50. };
  51. using ci_string = std::basic_string<char, ci_char_traits>;
  52. int main()
  53. {
  54. using namespace ranges;
  55. {
  56. int rgi[] = {1, 1, 1, 2, 3, 4, 4};
  57. std::vector<int> out;
  58. auto rng = rgi | views::unique;
  59. has_type<int &>(*begin(rng));
  60. CPP_assert(view_<decltype(rng)>);
  61. CPP_assert(bidirectional_range<decltype(rng)>);
  62. CPP_assert(!random_access_range<decltype(rng)>);
  63. CPP_assert(common_range<decltype(rng)>);
  64. CPP_assert(!sized_range<decltype(rng)>);
  65. CPP_assert(range<decltype(rng) const>);
  66. copy(rng, ranges::back_inserter(out));
  67. ::check_equal(out, {1, 2, 3, 4});
  68. ::check_equal(views::reverse(out), {4, 3, 2, 1});
  69. }
  70. {
  71. std::vector<ci_string> rgs{"hello", "HELLO", "bye", "Bye", "BYE"};
  72. auto rng = rgs | views::unique;
  73. has_type<ci_string &>(*begin(rng));
  74. CPP_assert(view_<decltype(rng)>);
  75. CPP_assert(bidirectional_range<decltype(rng)>);
  76. CPP_assert(!random_access_range<decltype(rng)>);
  77. CPP_assert(common_range<decltype(rng)>);
  78. CPP_assert(!sized_range<decltype(rng)>);
  79. CPP_assert(range<decltype(rng) const>);
  80. auto fs = rng | views::transform([](ci_string s){return std::string(s.data(), s.size());});
  81. CPP_assert(view_<decltype(fs)>);
  82. CPP_assert(bidirectional_range<decltype(fs)>);
  83. ::check_equal(fs, {"hello","bye"});
  84. ::check_equal(views::reverse(fs), {"bye","hello"});
  85. }
  86. {
  87. int const rgi[] = {1, 1, 1, 2, 3, 4, 4, 42, 7};
  88. auto rng0 = views::delimit(rgi, 42) | views::reverse;
  89. // rng0 is mutable-only...
  90. CPP_assert(forward_range<decltype(rng0)>);
  91. CPP_assert(!forward_range<decltype(rng0) const>);
  92. // ...and composable
  93. auto rng = rng0 | views::unique(equal_to{});
  94. CPP_assert(view_<decltype(rng)>);
  95. CPP_assert(bidirectional_range<decltype(rng)>);
  96. CPP_assert(!random_access_range<decltype(rng)>);
  97. CPP_assert(common_range<decltype(rng)>);
  98. CPP_assert(!sized_range<decltype(rng)>);
  99. ::check_equal(rng, {4, 3, 2, 1});
  100. }
  101. {
  102. auto const caseInsensitiveCompare = [](const std::string& s1, const std::string& s2){
  103. if (s1.size() != s2.size())
  104. return false;
  105. for (unsigned i = 0; i < s1.size(); i++)
  106. if (toupper(s1[i]) != toupper(s2[i]))
  107. return false;
  108. return true;
  109. };
  110. std::vector<std::string> rgs{"hello", "HELLO", "bye", "Bye", "BYE"};
  111. auto rng = rgs | views::unique(caseInsensitiveCompare);
  112. has_type<std::string &>(*begin(rng));
  113. CPP_assert(view_<decltype(rng)>);
  114. CPP_assert(bidirectional_range<decltype(rng)>);
  115. CPP_assert(!random_access_range<decltype(rng)>);
  116. CPP_assert(common_range<decltype(rng)>);
  117. CPP_assert(!sized_range<decltype(rng)>);
  118. CPP_assert(range<decltype(rng) const>);
  119. CPP_assert(view_<decltype(rng)>);
  120. CPP_assert(bidirectional_range<decltype(rng)>);
  121. ::check_equal(rng, {"hello","bye"});
  122. ::check_equal(views::reverse(rng), {"bye","hello"});
  123. }
  124. {
  125. int const rgi[] = {-1, 1, -1, 2, 3, 4, -4, 42, 7};
  126. auto rng0 = views::delimit(rgi, 42) | views::reverse;
  127. // rng0 is mutable-only...
  128. CPP_assert(forward_range<decltype(rng0)>);
  129. CPP_assert(!forward_range<decltype(rng0) const>);
  130. // ...and composable
  131. auto rng = rng0 | views::unique([](const int& n1, const int& n2){ return n1==n2 || n1==-n2; })
  132. | views::transform([](const int& n){ return n > 0 ? n: -n;});
  133. CPP_assert(view_<decltype(rng)>);
  134. CPP_assert(bidirectional_range<decltype(rng)>);
  135. CPP_assert(!random_access_range<decltype(rng)>);
  136. CPP_assert(common_range<decltype(rng)>);
  137. CPP_assert(!sized_range<decltype(rng)>);
  138. ::check_equal(rng, {4, 3, 2, 1});
  139. }
  140. return test_result();
  141. }