common_iterator.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Range v3 library
  2. //
  3. // Copyright Eric Niebler 2015-present
  4. // Copyright Casey Carter 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. //
  13. #include <algorithm>
  14. #include <numeric>
  15. #include <range/v3/iterator/common_iterator.hpp>
  16. #include <range/v3/iterator/unreachable_sentinel.hpp>
  17. #include "../simple_test.hpp"
  18. #include "../test_iterators.hpp"
  19. RANGES_DIAGNOSTIC_IGNORE_UNNEEDED_MEMBER
  20. namespace {
  21. struct silly_arrow_cursor {
  22. int read() const { return 0; }
  23. void next() {}
  24. int arrow() const { return 42; }
  25. };
  26. int forty_two = 42;
  27. struct lvalue_iterator {
  28. using difference_type = int;
  29. using value_type = int;
  30. int& operator*() const { return forty_two; }
  31. lvalue_iterator& operator++() & { return *this; }
  32. lvalue_iterator operator++(int) & { return *this; }
  33. };
  34. struct xvalue_iterator : lvalue_iterator {
  35. int&& operator*() const { return std::move(forty_two); }
  36. xvalue_iterator& operator++() & { return *this; }
  37. xvalue_iterator operator++(int) & { return *this; }
  38. };
  39. struct proxy_cursor {
  40. int read() const { return 42; }
  41. void next() {}
  42. };
  43. void test_operator_arrow() {
  44. // I is a pointer type
  45. {
  46. int i = 42;
  47. auto ci = ranges::common_iterator<int*, ranges::unreachable_sentinel_t>{&i};
  48. CPP_assert(ranges::same_as<int*, decltype(ci.operator->())>);
  49. CHECK(ci.operator->() == &i);
  50. }
  51. // the expression i.operator->() is well-formed
  52. {
  53. using I = ranges::basic_iterator<silly_arrow_cursor>;
  54. auto ci = ranges::common_iterator<I, ranges::unreachable_sentinel_t>{};
  55. CPP_assert(ranges::same_as<I, decltype(ci.operator->())>);
  56. CHECK(ci.operator->().operator->() == 42);
  57. }
  58. // the expression *i is a glvalue [lvalue case]
  59. {
  60. auto ci = ranges::common_iterator<lvalue_iterator, ranges::unreachable_sentinel_t>{};
  61. CPP_assert(ranges::same_as<int*, decltype(ci.operator->())>);
  62. CHECK(ci.operator->() == &forty_two);
  63. }
  64. // the expression *i is a glvalue [xvalue case]
  65. {
  66. auto ci = ranges::common_iterator<xvalue_iterator, ranges::unreachable_sentinel_t>{};
  67. CPP_assert(ranges::same_as<int*, decltype(ci.operator->())>);
  68. CHECK(ci.operator->() == &forty_two);
  69. }
  70. // Otherwise, returns a proxy object
  71. {
  72. using I = ranges::basic_iterator<proxy_cursor>;
  73. auto ci = ranges::common_iterator<I, ranges::unreachable_sentinel_t>{};
  74. using A = decltype(ci.operator->());
  75. CPP_assert(std::is_class<A>::value);
  76. CPP_assert(!std::is_same<I, A>::value);
  77. CHECK(*ci.operator->().operator->() == 42);
  78. }
  79. }
  80. }
  81. int main() {
  82. {
  83. CPP_assert(
  84. ranges::forward_iterator<
  85. ranges::common_iterator<
  86. BidirectionalIterator<const char *>,
  87. Sentinel<const char *>>>);
  88. CPP_assert(
  89. !ranges::bidirectional_iterator<
  90. ranges::common_iterator<
  91. BidirectionalIterator<const char *>,
  92. Sentinel<const char *>>>);
  93. CPP_assert(
  94. std::is_same<
  95. ranges::common_reference<
  96. ranges::common_iterator<
  97. BidirectionalIterator<const char *>,
  98. Sentinel<const char *>
  99. >&,
  100. ranges::common_iterator<
  101. BidirectionalIterator<const char *>,
  102. Sentinel<const char *>
  103. >
  104. >::type,
  105. ranges::common_iterator<
  106. BidirectionalIterator<const char *>,
  107. Sentinel<const char *>
  108. >
  109. >::value);
  110. // Sized iterator range tests
  111. CPP_assert(
  112. !ranges::sized_sentinel_for<
  113. ranges::common_iterator<
  114. ForwardIterator<int*>,
  115. Sentinel<int*, true> >,
  116. ranges::common_iterator<
  117. ForwardIterator<int*>,
  118. Sentinel<int*, true> > >);
  119. CPP_assert(
  120. ranges::sized_sentinel_for<
  121. ranges::common_iterator<
  122. RandomAccessIterator<int*>,
  123. Sentinel<int*, true> >,
  124. ranges::common_iterator<
  125. RandomAccessIterator<int*>,
  126. Sentinel<int*, true> > >);
  127. CPP_assert(
  128. !ranges::sized_sentinel_for<
  129. ranges::common_iterator<
  130. RandomAccessIterator<int*>,
  131. Sentinel<int*, false> >,
  132. ranges::common_iterator<
  133. RandomAccessIterator<int*>,
  134. Sentinel<int*, false> > >);
  135. }
  136. {
  137. int rgi[] {0,1,2,3,4,5,6,7,8,9};
  138. using CI = ranges::common_iterator<
  139. RandomAccessIterator<int*>,
  140. Sentinel<int*>>;
  141. CI first{RandomAccessIterator<int*>{rgi}};
  142. CI last{Sentinel<int*>{rgi+10}};
  143. CHECK(std::accumulate(first, last, 0, std::plus<int>{}) == 45);
  144. }
  145. test_operator_arrow();
  146. return test_result();
  147. }