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
10 // UNSUPPORTED: libcpp-no-concepts
11 // UNSUPPORTED: gcc-10
12 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
13 
14 // std::views::all;
15 
16 #include <ranges>
17 
18 #include <cassert>
19 #include "test_macros.h"
20 #include "test_iterators.h"
21 
22 int globalBuff[8];
23 
24 template<bool IsNoexcept>
25 struct View : std::ranges::view_base {
26   int start_ = 0;
27   explicit View() noexcept(IsNoexcept) = default;
28   constexpr explicit View(int start) : start_(start) {}
29   View(View&&) noexcept(IsNoexcept) = default;
30   View& operator=(View&&) noexcept(IsNoexcept) = default;
31   friend constexpr int* begin(View& view) { return globalBuff + view.start_; }
32   friend constexpr int* begin(View const& view) { return globalBuff + view.start_; }
33   friend constexpr int* end(View&) { return globalBuff + 8; }
34   friend constexpr int* end(View const&) { return globalBuff + 8; }
35 };
36 static_assert(std::ranges::view<View<true>>);
37 static_assert(std::ranges::view<View<false>>);
38 
39 template<bool IsNoexcept>
40 struct CopyableView : std::ranges::view_base {
41   int start_ = 0;
42   explicit CopyableView() noexcept(IsNoexcept) = default;
43   CopyableView(CopyableView const&) noexcept(IsNoexcept) = default;
44   CopyableView& operator=(CopyableView const&) noexcept(IsNoexcept) = default;
45   constexpr explicit CopyableView(int start) noexcept : start_(start) {}
46   friend constexpr int* begin(CopyableView& view) { return globalBuff + view.start_; }
47   friend constexpr int* begin(CopyableView const& view) { return globalBuff + view.start_; }
48   friend constexpr int* end(CopyableView&) { return globalBuff + 8; }
49   friend constexpr int* end(CopyableView const&) { return globalBuff + 8; }
50 };
51 static_assert(std::ranges::view<CopyableView<true>>);
52 static_assert(std::ranges::view<CopyableView<false>>);
53 
54 struct Range {
55   int start_;
56   constexpr explicit Range(int start) noexcept : start_(start) {}
57   friend constexpr int* begin(Range const& range) { return globalBuff + range.start_; }
58   friend constexpr int* begin(Range& range) { return globalBuff + range.start_; }
59   friend constexpr int* end(Range const&) { return globalBuff + 8; }
60   friend constexpr int* end(Range&) { return globalBuff + 8; }
61 };
62 
63 struct BorrowableRange {
64   int start_;
65   constexpr explicit BorrowableRange(int start) noexcept : start_(start) {}
66   friend constexpr int* begin(BorrowableRange const& range) { return globalBuff + range.start_; }
67   friend constexpr int* begin(BorrowableRange& range) { return globalBuff + range.start_; }
68   friend constexpr int* end(BorrowableRange const&) { return globalBuff + 8; }
69   friend constexpr int* end(BorrowableRange&) { return globalBuff + 8; }
70 };
71 template<>
72 inline constexpr bool std::ranges::enable_borrowed_range<BorrowableRange> = true;
73 
74 struct RandomAccessRange {
75   struct sentinel {
76     friend constexpr bool operator==(sentinel, const random_access_iterator<int*> rai) { return rai.base() == globalBuff + 8; }
77     friend constexpr std::ptrdiff_t operator-(sentinel, random_access_iterator<int*>) { return -8; }
78     friend constexpr std::ptrdiff_t operator-(random_access_iterator<int*>, sentinel) { return 8; }
79   };
80 
81   constexpr random_access_iterator<int*> begin() { return random_access_iterator<int*>{globalBuff}; }
82   constexpr sentinel end() { return {}; }
83 };
84 template<>
85 inline constexpr bool std::ranges::enable_borrowed_range<RandomAccessRange> = true;
86 
87 constexpr bool test() {
88   {
89     ASSERT_SAME_TYPE(decltype(std::views::all(View<true>())), View<true>);
90     static_assert(noexcept(std::views::all(View<true>())));
91     static_assert(!noexcept(std::views::all(View<false>())));
92 
93     auto viewCopy = std::views::all(View<true>(2));
94     ASSERT_SAME_TYPE(decltype(viewCopy), View<true>);
95     assert(std::ranges::begin(viewCopy) == globalBuff + 2);
96     assert(std::ranges::end(viewCopy) == globalBuff + 8);
97   }
98 
99   {
100     ASSERT_SAME_TYPE(decltype(std::views::all(std::declval<const CopyableView<true>&>())), CopyableView<true>);
101     static_assert(noexcept(std::views::all(CopyableView<true>())));
102     static_assert(!noexcept(std::views::all(CopyableView<false>())));
103 
104     CopyableView<true> view(2);
105     auto viewCopy = std::views::all(view);
106     ASSERT_SAME_TYPE(decltype(viewCopy), CopyableView<true>);
107     assert(std::ranges::begin(viewCopy) == globalBuff + 2);
108     assert(std::ranges::end(viewCopy) == globalBuff + 8);
109   }
110 
111   {
112     Range range(2);
113     auto ref = std::views::all(range);
114     ASSERT_SAME_TYPE(decltype(ref), std::ranges::ref_view<Range>);
115     assert(std::ranges::begin(ref) == globalBuff + 2);
116     assert(std::ranges::end(ref) == globalBuff + 8);
117 
118     static_assert(!std::is_invocable_v<decltype(std::views::all), Range>);
119   }
120 
121   {
122     const Range range(2);
123     auto ref = std::views::all(range);
124     static_assert(!noexcept(std::views::all(range)));
125     ASSERT_SAME_TYPE(decltype(ref), std::ranges::ref_view<const Range>);
126     assert(std::ranges::begin(ref) == globalBuff + 2);
127     assert(std::ranges::end(ref) == globalBuff + 8);
128   }
129 
130   {
131     auto subrange = std::views::all(BorrowableRange(2));
132     static_assert(!noexcept(std::views::all(BorrowableRange(2))));
133     ASSERT_SAME_TYPE(decltype(subrange), std::ranges::subrange<int*>);
134     assert(std::ranges::begin(subrange) == globalBuff + 2);
135     assert(std::ranges::end(subrange) == globalBuff + 8);
136   }
137 
138   {
139     auto subrange = std::views::all(RandomAccessRange());
140     ASSERT_SAME_TYPE(decltype(subrange),
141                      std::ranges::subrange<random_access_iterator<int*>, RandomAccessRange::sentinel>);
142     assert(std::ranges::begin(subrange).base() == globalBuff);
143     assert(std::ranges::end(subrange) == std::ranges::begin(subrange) + 8);
144   }
145 
146   return true;
147 }
148 
149 int main(int, char**) {
150   test();
151   static_assert(test());
152 
153   return 0;
154 }
155