shared.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Range v3 library
  2. //
  3. // Copyright Filip Matzner 2017
  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 <list>
  12. #include <memory>
  13. #include <tuple>
  14. #include <vector>
  15. #include <range/v3/core.hpp>
  16. #include <range/v3/algorithm/for_each.hpp>
  17. #include <range/v3/view/cycle.hpp>
  18. #include <range/v3/view/for_each.hpp>
  19. #include <range/v3/view/iota.hpp>
  20. #include <range/v3/view/join.hpp>
  21. #include <range/v3/view/remove_if.hpp>
  22. #include <range/v3/view/repeat.hpp>
  23. #include <range/v3/view/reverse.hpp>
  24. #include <range/v3/experimental/view/shared.hpp>
  25. #include <range/v3/view/take.hpp>
  26. #include "../../simple_test.hpp"
  27. #include "../../test_utils.hpp"
  28. using namespace ranges;
  29. template<typename T>
  30. void check_shared_contents()
  31. {
  32. // build two instances sharing the same range
  33. experimental::shared_view<T> view1 = experimental::views::shared(T{1, 1, 1, 2, 3, 4, 4});
  34. experimental::shared_view<T> view2 = view1;
  35. // check the length of the views
  36. CHECK(view1.size() == 7u);
  37. CHECK(view2.size() == 7u);
  38. // check the stored numbers
  39. auto check_values = [](experimental::shared_view<T> & rng) {
  40. ::check_equal(views::cycle(rng) | views::take(10), {1, 1, 1, 2, 3, 4, 4, 1, 1, 1});
  41. ::check_equal(views::all(rng) | views::take(5), {1, 1, 1, 2, 3});
  42. ::check_equal(rng | views::take(5), {1, 1, 1, 2, 3});
  43. ::check_equal(rng, {1, 1, 1, 2, 3, 4, 4});
  44. };
  45. check_values(view1);
  46. check_values(view2);
  47. // check that changes are shared
  48. *(++begin(view1)) = 7;
  49. CHECK(*(++begin(view2)) == 7);
  50. *begin(view2) = 3;
  51. CHECK(*begin(view1) == 3);
  52. }
  53. int main()
  54. {
  55. // check shared random access range
  56. check_shared_contents<std::vector<int>>();
  57. // check shared bidirectional range
  58. check_shared_contents<std::list<int>>();
  59. {
  60. // check the piped construction from an rvalue
  61. std::vector<int> base_vec = {1, 2, 2, 8, 2, 7};
  62. auto vec_view = std::move(base_vec) | experimental::views::shared;
  63. CHECK(vec_view.size() == 6u);
  64. ::check_equal(vec_view, {1, 2, 2, 8, 2, 7});
  65. }
  66. {
  67. // test bidirectional range
  68. auto list_view = std::list<int>{1, 2, 3} | experimental::views::shared;
  69. CHECK(list_view.size() == 3u);
  70. has_type<int &>(*begin(list_view));
  71. CPP_assert(sized_range<decltype(list_view)>);
  72. CPP_assert(common_range<decltype(list_view)>);
  73. CPP_assert(bidirectional_range<decltype(list_view)>);
  74. CPP_assert(!random_access_range<decltype(list_view)>);
  75. // test bidirectional range iterator
  76. CHECK(*begin(list_view) == 1);
  77. CHECK(*prev(end(list_view)) == 3);
  78. }
  79. {
  80. // test random access range
  81. auto vec_view = std::vector<int>{1, 2, 3} | experimental::views::shared;
  82. CHECK(vec_view.size() == 3u);
  83. has_type<int &>(*begin(vec_view));
  84. CPP_assert(sized_range<decltype(vec_view)>);
  85. CPP_assert(common_range<decltype(vec_view)>);
  86. CPP_assert(random_access_range<decltype(vec_view)>);
  87. CHECK(vec_view[0] == 1);
  88. CHECK(vec_view[1] == 2);
  89. CHECK(vec_view[2] == 3);
  90. }
  91. {
  92. // check temporary value in views::transform
  93. auto f = [](unsigned a){ return std::vector<unsigned>(a, a); };
  94. auto vec_view =
  95. views::iota(1u)
  96. | views::transform(f)
  97. | views::transform(experimental::views::shared)
  98. | views::join
  99. | views::take(10);
  100. ::check_equal(vec_view, {1u, 2u, 2u, 3u, 3u, 3u, 4u, 4u, 4u, 4u});
  101. }
  102. {
  103. // check temporary value in views::for_each
  104. std::vector<int> base_vec{1, 2, 3};
  105. auto vec_view =
  106. views::repeat(base_vec)
  107. | views::for_each([](std::vector<int> tmp) {
  108. return yield_from(std::move(tmp) | experimental::views::shared | views::reverse);
  109. })
  110. | views::take(7);
  111. ::check_equal(vec_view, {3, 2, 1, 3, 2, 1, 3});
  112. }
  113. {
  114. // check temporary value in views::for_each without the yield_from
  115. std::vector<int> base_vec{1, 2, 3};
  116. auto vec_view =
  117. views::repeat(base_vec)
  118. | views::for_each([](std::vector<int> tmp) {
  119. return std::move(tmp) | experimental::views::shared | views::reverse;
  120. })
  121. | views::take(7);
  122. ::check_equal(vec_view, {3, 2, 1, 3, 2, 1, 3});
  123. }
  124. return test_result();
  125. }