access.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // Range v3 library
  2. //
  3. // Copyright Casey Carter 2016
  4. // Copyright Eric Niebler 2018
  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 <range/v3/range/access.hpp>
  13. #include <range/v3/range/primitives.hpp>
  14. #include <range/v3/view/subrange.hpp>
  15. #include <range/v3/view/ref.hpp>
  16. #include <range/v3/view/iota.hpp>
  17. #include <range/v3/algorithm/find.hpp>
  18. #include <vector>
  19. #include "../simple_test.hpp"
  20. #if defined(__clang__)
  21. RANGES_DIAGNOSTIC_IGNORE("-Wunused-const-variable")
  22. #endif
  23. void test_range_access_ambiguity()
  24. {
  25. std::vector<ranges::reverse_iterator<int*>> vri{};
  26. using namespace ranges;
  27. (void)begin(vri);
  28. (void)end(vri);
  29. (void)cbegin(vri);
  30. (void)cend(vri);
  31. (void)rbegin(vri);
  32. (void)rend(vri);
  33. (void)crbegin(vri);
  34. (void)crend(vri);
  35. }
  36. void test_initializer_list()
  37. {
  38. std::initializer_list<int> il = {0,1,2};
  39. {
  40. int count = 0;
  41. for(auto p = ranges::begin(il), e = ranges::end(il); p != e; ++p) {
  42. CHECK(*p == count++);
  43. }
  44. }
  45. {
  46. int count = 3;
  47. for(auto p = ranges::rbegin(il), e = ranges::rend(il); p != e; ++p) {
  48. CHECK(*p == --count);
  49. }
  50. }
  51. CHECK(ranges::size(il) == std::size_t{3});
  52. CHECK(ranges::data(il) == &*il.begin());
  53. CHECK(ranges::empty(il) == false);
  54. }
  55. template<class Value, typename T, T... Is>
  56. void test_array(std::integer_sequence<T, Is...>)
  57. {
  58. Value a[sizeof...(Is)] = { Is... };
  59. {
  60. int count = 0;
  61. for(auto p = ranges::begin(a), e = ranges::end(a); p != e; ++p) {
  62. CHECK(*p == count++);
  63. }
  64. }
  65. {
  66. int count = sizeof...(Is);
  67. for(auto p = ranges::rbegin(a), e = ranges::rend(a); p != e; ++p) {
  68. CHECK(*p == --count);
  69. }
  70. }
  71. CHECK(ranges::size(a) == sizeof...(Is));
  72. CHECK(ranges::data(a) == a + 0);
  73. CHECK(ranges::empty(a) == false);
  74. }
  75. namespace begin_testing
  76. {
  77. template<class R>
  78. CPP_requires(can_begin_,
  79. requires(R&& r) //
  80. (
  81. ranges::begin((R &&) r)
  82. ));
  83. template<class R>
  84. CPP_concept can_begin =
  85. CPP_requires_ref(can_begin_, R);
  86. template<class R>
  87. CPP_requires(can_cbegin_,
  88. requires(R&& r) //
  89. (
  90. ranges::cbegin((R &&) r)
  91. ));
  92. template<class R>
  93. CPP_concept can_cbegin =
  94. CPP_requires_ref(can_cbegin_, R);
  95. struct A
  96. {
  97. int* begin();
  98. int* end();
  99. int const * begin() const;
  100. int const * end() const;
  101. };
  102. struct B : A {};
  103. void* begin(B&);
  104. struct C : A {};
  105. void begin(C&);
  106. struct D : A {};
  107. char* begin(D&);
  108. void test()
  109. {
  110. // Valid
  111. CPP_assert(can_begin<int(&)[2]>);
  112. CPP_assert(ranges::same_as<decltype(ranges::begin(std::declval<int(&)[2]>())), int*>);
  113. CPP_assert(can_begin<int const(&)[2]>);
  114. CPP_assert(ranges::same_as<decltype(ranges::begin(std::declval<int const(&)[2]>())), int const *>);
  115. CPP_assert(can_cbegin<int(&)[2]>);
  116. CPP_assert(ranges::same_as<decltype(ranges::cbegin(std::declval<int(&)[2]>())), int const *>);
  117. CPP_assert(can_cbegin<int const(&)[2]>);
  118. CPP_assert(ranges::same_as<decltype(ranges::cbegin(std::declval<int const(&)[2]>())), int const *>);
  119. #ifndef RANGES_WORKAROUND_MSVC_573728
  120. // Ill-formed: array rvalue
  121. CPP_assert(!can_begin<int(&&)[2]>);
  122. CPP_assert(!can_begin<int const(&&)[2]>);
  123. CPP_assert(!can_cbegin<int(&&)[2]>);
  124. CPP_assert(!can_cbegin<int const(&&)[2]>);
  125. #endif // RANGES_WORKAROUND_MSVC_573728
  126. // Valid: only member begin
  127. CPP_assert(can_begin<A&>);
  128. CPP_assert(!can_begin<A>);
  129. CPP_assert(ranges::same_as<decltype(ranges::begin(std::declval<A&>())), int*>);
  130. CPP_assert(can_begin<const A&>);
  131. CPP_assert(!can_begin<const A>);
  132. CPP_assert(ranges::same_as<decltype(ranges::begin(std::declval<const A&>())), int const *>);
  133. // Valid: Both member and non-member begin, but non-member returns non-Iterator.
  134. CPP_assert(can_begin<B&>);
  135. CPP_assert(!can_begin<B>);
  136. CPP_assert(ranges::same_as<decltype(ranges::begin(std::declval<B&>())), int*>);
  137. CPP_assert(can_begin<const B&>);
  138. CPP_assert(!can_begin<const B>);
  139. CPP_assert(ranges::same_as<decltype(ranges::begin(std::declval<const B&>())), int const *>);
  140. // Valid: Both member and non-member begin, but non-member returns non-Iterator.
  141. CPP_assert(can_begin<C&>);
  142. CPP_assert(!can_begin<C>);
  143. CPP_assert(can_begin<const C&>);
  144. CPP_assert(!can_begin<const C>);
  145. // Valid: Prefer member begin
  146. CPP_assert(can_begin<D&>);
  147. CPP_assert(!can_begin<D>);
  148. CPP_assert(ranges::same_as<int*, decltype(ranges::begin(std::declval<D&>()))>);
  149. CPP_assert(can_begin<const D&>);
  150. CPP_assert(!can_begin<const D>);
  151. CPP_assert(ranges::same_as<int const *, decltype(ranges::begin(std::declval<const D&>()))>);
  152. {
  153. using T = std::initializer_list<int>;
  154. // Valid: begin accepts lvalue initializer_list
  155. CPP_assert(ranges::same_as<int const *, decltype(ranges::begin(std::declval<T&>()))>);
  156. CPP_assert(ranges::same_as<int const *, decltype(ranges::begin(std::declval<const T&>()))>);
  157. CPP_assert(!can_begin<T>);
  158. CPP_assert(!can_begin<T const>);
  159. }
  160. CPP_assert(can_begin<ranges::subrange<int*, int*>&>);
  161. CPP_assert(can_begin<const ranges::subrange<int*, int*>&>);
  162. CPP_assert(can_begin<ranges::subrange<int*, int*>>);
  163. CPP_assert(can_begin<const ranges::subrange<int*, int*>>);
  164. CPP_assert(can_cbegin<ranges::subrange<int*, int*>&>);
  165. CPP_assert(can_cbegin<const ranges::subrange<int*, int*>&>);
  166. CPP_assert(can_cbegin<ranges::subrange<int*, int*>>);
  167. CPP_assert(can_cbegin<const ranges::subrange<int*, int*>>);
  168. CPP_assert(can_begin<ranges::ref_view<int[5]>&>);
  169. CPP_assert(can_begin<const ranges::ref_view<int[5]>&>);
  170. CPP_assert(can_begin<ranges::ref_view<int[5]>>);
  171. CPP_assert(can_begin<const ranges::ref_view<int[5]>>);
  172. CPP_assert(can_cbegin<ranges::ref_view<int[5]>&>);
  173. CPP_assert(can_cbegin<const ranges::ref_view<int[5]>&>);
  174. CPP_assert(can_cbegin<ranges::ref_view<int[5]>>);
  175. CPP_assert(can_cbegin<const ranges::ref_view<int[5]>>);
  176. // TODO
  177. // CPP_assert(can_begin<ranges::iota_view<int, int>&>);
  178. // CPP_assert(can_begin<const ranges::iota_view<int, int>&>);
  179. // CPP_assert(can_begin<ranges::iota_view<int, int>>);
  180. // CPP_assert(can_begin<const ranges::iota_view<int, int>>);
  181. // CPP_assert(can_cbegin<ranges::iota_view<int, int>&>);
  182. // CPP_assert(can_cbegin<const ranges::iota_view<int, int>&>);
  183. // CPP_assert(can_cbegin<ranges::iota_view<int, int>>);
  184. // CPP_assert(can_cbegin<const ranges::iota_view<int, int>>);
  185. }
  186. } // namespace begin_testing
  187. namespace X
  188. {
  189. template<class T, std::size_t N>
  190. struct array
  191. {
  192. T elements_[N];
  193. constexpr bool empty() const noexcept { return N == 0; }
  194. constexpr T* data() noexcept { return elements_; }
  195. constexpr T const *data() const noexcept { return elements_; }
  196. };
  197. template<class T, std::size_t N>
  198. constexpr T* begin(array<T, N> &a) noexcept { return a.elements_; }
  199. template<class T, std::size_t N>
  200. constexpr T* end(array<T, N> &a) noexcept { return a.elements_ + N; }
  201. template<class T, std::size_t N>
  202. constexpr T const *begin(array<T, N> const &a) noexcept { return a.elements_; }
  203. template<class T, std::size_t N>
  204. constexpr T const *end(array<T, N> const &a) noexcept { return a.elements_ + N; }
  205. } // namespace X
  206. using I = int*;
  207. using CI = int const *;
  208. CPP_assert(ranges::input_or_output_iterator<I>);
  209. CPP_assert(ranges::input_or_output_iterator<CI>);
  210. #if defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201603L
  211. void test_string_view_p0970()
  212. {
  213. // basic_string_views are non-dangling
  214. using I2 = ranges::iterator_t<std::string_view>;
  215. CPP_assert(ranges::same_as<I2, decltype(ranges::begin(std::declval<std::string_view>()))>);
  216. CPP_assert(ranges::same_as<I2, decltype(ranges::end(std::declval<std::string_view>()))>);
  217. CPP_assert(ranges::same_as<I2, decltype(ranges::begin(std::declval<const std::string_view>()))>);
  218. CPP_assert(ranges::same_as<I2, decltype(ranges::end(std::declval<const std::string_view>()))>);
  219. {
  220. const char hw[] = "Hello, World!";
  221. auto result = ranges::find(std::string_view{hw}, 'W');
  222. CPP_assert(ranges::same_as<I2, decltype(result)>);
  223. CHECK(result == std::string_view{hw}.begin() + 7);
  224. }
  225. }
  226. #endif
  227. int main()
  228. {
  229. using namespace ranges;
  230. static constexpr X::array<int, 4> some_ints = {{0,1,2,3}};
  231. CPP_assert(begin_testing::can_begin<X::array<int, 4> &>);
  232. CPP_assert(begin_testing::can_begin<X::array<int, 4> const &>);
  233. CPP_assert(!begin_testing::can_begin<X::array<int, 4>>);
  234. CPP_assert(!begin_testing::can_begin<X::array<int, 4> const>);
  235. CPP_assert(begin_testing::can_cbegin<X::array<int, 4> &>);
  236. CPP_assert(begin_testing::can_cbegin<X::array<int, 4> const &>);
  237. CPP_assert(!begin_testing::can_cbegin<X::array<int, 4>>);
  238. CPP_assert(!begin_testing::can_cbegin<X::array<int, 4> const>);
  239. constexpr auto first = begin(some_ints);
  240. constexpr auto last = end(some_ints);
  241. CPP_assert(ranges::same_as<const CI, decltype(first)>);
  242. CPP_assert(ranges::same_as<const CI, decltype(last)>);
  243. static_assert(first == cbegin(some_ints), "");
  244. static_assert(last == cend(some_ints), "");
  245. static_assert(noexcept(begin(some_ints)), "");
  246. static_assert(noexcept(end(some_ints)), "");
  247. static_assert(noexcept(cbegin(some_ints)), "");
  248. static_assert(noexcept(cend(some_ints)), "");
  249. static_assert(noexcept(empty(some_ints)), "");
  250. static_assert(noexcept(data(some_ints)), "");
  251. constexpr bool output = false;
  252. static_assert(!empty(some_ints), "");
  253. if(output)
  254. std::cout << '{';
  255. auto is_first = true;
  256. auto count = 0;
  257. for(auto&& i : some_ints)
  258. {
  259. CHECK(i == count++);
  260. if(is_first)
  261. is_first = false;
  262. else
  263. if(output) std::cout << ", ";
  264. if(output) std::cout << i;
  265. }
  266. if(output)
  267. std::cout << "}\n";
  268. test_initializer_list();
  269. test_array<int>(std::make_integer_sequence<int, 3>{});
  270. test_array<int const>(std::make_integer_sequence<int, 3>{});
  271. begin_testing::test();
  272. #if defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201603L
  273. test_string_view_p0970();
  274. #endif
  275. return ::test_result();
  276. }