xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.as.rvalue/begin.pass.cpp (revision f56dfb78aa3fcc96bf7e5b6c3bdff8fa620aefd1)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10 
11 // constexpr auto begin()
12 // constexpr auto begin() const
13 
14 #include <array>
15 #include <cassert>
16 #include <concepts>
17 #include <ranges>
18 
19 #include "test_iterators.h"
20 
21 struct SimpleView : std::ranges::view_base {
22   int* begin() const;
23   int* end() const;
24 };
25 
26 struct NonSimpleView : std::ranges::view_base {
27   char* begin();
28   char* end();
29   int* begin() const;
30   int* end() const;
31 };
32 
33 struct NonConstView : std::ranges::view_base {
34   char* begin();
35   char* end();
36 };
37 
38 template <class T>
39 concept HasBegin = requires(T t) { t.begin(); };
40 
41 static_assert(HasBegin<std::ranges::as_rvalue_view<SimpleView>>);
42 static_assert(HasBegin<const std::ranges::as_rvalue_view<SimpleView>>);
43 static_assert(HasBegin<std::ranges::as_rvalue_view<NonSimpleView>>);
44 static_assert(HasBegin<const std::ranges::as_rvalue_view<NonSimpleView>>);
45 static_assert(HasBegin<std::ranges::as_rvalue_view<NonConstView>>);
46 static_assert(!HasBegin<const std::ranges::as_rvalue_view<NonConstView>>);
47 
48 template <class Iter, class Sent>
test_range()49 constexpr void test_range() {
50   int a[] = {1, 2};
51   std::ranges::subrange range(Iter(std::begin(a)), Sent(Iter(std::end(a))));
52   std::ranges::as_rvalue_view view(std::move(range));
53   std::same_as<std::move_iterator<Iter>> decltype(auto) iter = view.begin();
54   assert(base(iter.base()) == std::begin(a));
55 }
56 
57 template <class Iter, class Sent>
58 class WrapRange {
59   Iter iter_;
60   Sent sent_;
61 
62 public:
WrapRange(Iter iter,Sent sent)63   constexpr WrapRange(Iter iter, Sent sent) : iter_(std::move(iter)), sent_(std::move(sent)) {}
64 
begin() const65   constexpr Iter begin() const { return iter_; }
end() const66   constexpr Sent end() const { return sent_; }
67 };
68 
69 template <class Iter, class Sent>
70 WrapRange(Iter, Sent) -> WrapRange<Iter, Sent>;
71 
72 template <class Iter, class Sent>
test_const_range()73 constexpr void test_const_range() {
74   int a[]    = {1, 2};
75   auto range = WrapRange{Iter(a), Sent(Iter(a + 2))};
76   const std::ranges::as_rvalue_view view(std::views::all(range));
77   std::same_as<std::move_iterator<Iter>> decltype(auto) iter = view.begin();
78   assert(base(iter.base()) == std::begin(a));
79 }
80 
81 struct move_iterator_view : std::ranges::view_base {
beginmove_iterator_view82   constexpr std::move_iterator<int*> begin() const { return {}; }
endmove_iterator_view83   constexpr std::move_iterator<int*> end() const { return {}; }
84 };
85 
test()86 constexpr bool test() {
87   types::for_each(types::cpp20_input_iterator_list<int*>{}, []<class Iter> {
88     if constexpr (std::sentinel_for<Iter, Iter>)
89       test_range<Iter, Iter>();
90     test_range<Iter, sentinel_wrapper<Iter>>();
91     test_range<Iter, sized_sentinel<Iter>>();
92   });
93 
94   types::for_each(types::forward_iterator_list<const int*>{}, []<class Iter> {
95     test_const_range<Iter, Iter>();
96     test_const_range<Iter, sentinel_wrapper<Iter>>();
97     test_const_range<Iter, sized_sentinel<Iter>>();
98   });
99 
100   { // check that with a std::move_iterator begin() doesn't return move_iterator<move_iterator<T>>
101     std::ranges::as_rvalue_view view{move_iterator_view{}};
102     std::same_as<std::move_iterator<int*>> decltype(auto) it = view.begin();
103     assert(it == std::move_iterator<int*>{});
104   }
105 
106   return true;
107 }
108 
main(int,char **)109 int main(int, char**) {
110   test();
111   static_assert(test());
112 
113   return 0;
114 }
115