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-has-no-incomplete-ranges
11
12 // constexpr iterator& operator--();
13 // requires ref-is-glvalue && bidirectional_range<Base> &&
14 // bidirectional_range<range_reference_t<Base>> &&
15 // common_range<range_reference_t<Base>>;
16 // constexpr iterator operator--(int);
17 // requires ref-is-glvalue && bidirectional_range<Base> &&
18 // bidirectional_range<range_reference_t<Base>> &&
19 // common_range<range_reference_t<Base>>;
20
21 #include <cassert>
22 #include <ranges>
23 #include <type_traits>
24
25 #include "../types.h"
26
27 template <class T>
28 concept CanPreDecrement = requires(T& t) { --t; };
29
30 template <class T>
31 concept CanPostDecrement = requires(T& t) { t--; };
32
noDecrementTest(auto && jv)33 constexpr void noDecrementTest(auto&& jv) {
34 auto iter = jv.begin();
35 static_assert(!CanPreDecrement<decltype(iter)>);
36 static_assert(!CanPostDecrement<decltype(iter)>);
37 }
38
test()39 constexpr bool test() {
40 int buffer[4][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
41
42 {
43 // outer == ranges::end
44 std::ranges::join_view jv(buffer);
45 auto iter = std::next(jv.begin(), 16);
46 for (int i = 16; i != 0; --i) {
47 assert(*--iter == i);
48 }
49 }
50
51 {
52 // outer == ranges::end
53 std::ranges::join_view jv(buffer);
54 auto iter = std::next(jv.begin(), 13);
55 for (int i = 13; i != 0; --i) {
56 assert(*--iter == i);
57 }
58 }
59
60 {
61 // outer != ranges::end
62 std::ranges::join_view jv(buffer);
63 auto iter = std::next(jv.begin(), 12);
64 for (int i = 12; i != 0; --i) {
65 assert(*--iter == i);
66 }
67 }
68
69 {
70 // outer != ranges::end
71 std::ranges::join_view jv(buffer);
72 auto iter = std::next(jv.begin());
73 for (int i = 1; i != 0; --i) {
74 assert(*--iter == i);
75 }
76 }
77
78 {
79 int small[2][1] = {{1}, {2}};
80 std::ranges::join_view jv(small);
81 auto iter = std::next(jv.begin(), 2);
82 for (int i = 2; i != 0; --i) {
83 assert(*--iter == i);
84 }
85 }
86
87 {
88 #if defined(__GNUG__) && !defined(__clang__)
89 // This seems to be a gcc bug where evaluating the following code
90 // at compile time results in wrong array index
91 if (!std::is_constant_evaluated()) {
92 #endif
93 // skip empty inner
94 BidiCommonInner inners[4] = {buffer[0], {nullptr, 0}, {nullptr, 0}, buffer[1]};
95 std::ranges::join_view jv(inners);
96 auto iter = jv.end();
97 for (int i = 8; i != 0; --i) {
98 assert(*--iter == i);
99 }
100 #if defined(__GNUG__) && !defined(__clang__)
101 }
102 #endif
103 }
104
105 {
106 // basic type checking
107 std::ranges::join_view jv(buffer);
108 auto iter1 = std::ranges::next(jv.begin(), 4);
109 using iterator = decltype(iter1);
110
111 decltype(auto) iter2 = --iter1;
112 static_assert(std::same_as<decltype(iter2), iterator&>);
113 assert(&iter1 == &iter2);
114
115 std::same_as<iterator> decltype(auto) iter3 = iter1--;
116 assert(iter3 == std::next(iter1));
117 }
118
119 {
120 // !ref-is-glvalue
121 BidiCommonInner inners[2] = {buffer[0], buffer[1]};
122 InnerRValue<BidiCommonOuter<BidiCommonInner>> outer{inners};
123 std::ranges::join_view jv(outer);
124 noDecrementTest(jv);
125 }
126
127 {
128 // !bidirectional_range<Base>
129 BidiCommonInner inners[2] = {buffer[0], buffer[1]};
130 SimpleForwardCommonOuter<BidiCommonInner> outer{inners};
131 std::ranges::join_view jv(outer);
132 noDecrementTest(jv);
133 }
134
135 {
136 // !bidirectional_range<range_reference_t<Base>>
137 ForwardCommonInner inners[2] = {buffer[0], buffer[1]};
138 std::ranges::join_view jv(inners);
139 noDecrementTest(jv);
140 }
141
142 {
143 // LWG3313 `join_view::iterator::operator--` is incorrectly constrained
144 // `join_view::iterator` should not have `operator--` if
145 // !common_range<range_reference_t<Base>>
146 BidiNonCommonInner inners[2] = {buffer[0], buffer[1]};
147 std::ranges::join_view jv(inners);
148 auto iter = jv.begin();
149 static_assert(!CanPreDecrement<decltype(iter)>);
150 static_assert(!CanPostDecrement<decltype(iter)>);
151 }
152
153 return true;
154 }
155
main(int,char **)156 int main(int, char**) {
157 test();
158 static_assert(test());
159
160 return 0;
161 }
162