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 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
11 
12 // constexpr iterator& operator--() requires all-bidirectional<Const, Views...>;
13 // constexpr iterator operator--(int) requires all-bidirectional<Const, Views...>;
14 
15 #include <array>
16 #include <cassert>
17 #include <ranges>
18 #include <tuple>
19 
20 #include "../types.h"
21 
22 template <class Iter>
23 concept canDecrement = requires(Iter it) { --it; } || requires(Iter it) { it--; };
24 
25 struct NonBidi : IntBufferView {
26   using IntBufferView::IntBufferView;
27   using iterator = forward_iterator<int*>;
beginNonBidi28   constexpr iterator begin() const { return iterator(buffer_); }
endNonBidi29   constexpr sentinel_wrapper<iterator> end() const { return sentinel_wrapper<iterator>(iterator(buffer_ + size_)); }
30 };
31 
test()32 constexpr bool test() {
33   std::array a{1, 2, 3, 4};
34   std::array b{4.1, 3.2, 4.3};
35   {
36     // all random access
37     std::ranges::zip_view v(a, b, std::views::iota(0, 5));
38     auto it = v.end();
39     using Iter = decltype(it);
40 
41     static_assert(std::is_same_v<decltype(--it), Iter&>);
42     auto& it_ref = --it;
43     assert(&it_ref == &it);
44 
45     assert(&(std::get<0>(*it)) == &(a[2]));
46     assert(&(std::get<1>(*it)) == &(b[2]));
47     assert(std::get<2>(*it) == 2);
48 
49     static_assert(std::is_same_v<decltype(it--), Iter>);
50     it--;
51     assert(&(std::get<0>(*it)) == &(a[1]));
52     assert(&(std::get<1>(*it)) == &(b[1]));
53     assert(std::get<2>(*it) == 1);
54   }
55 
56   {
57     // all bidi+
58     int buffer[2] = {1, 2};
59 
60     std::ranges::zip_view v(BidiCommonView{buffer}, std::views::iota(0, 5));
61     auto it = v.begin();
62     using Iter = decltype(it);
63 
64     ++it;
65     ++it;
66 
67     static_assert(std::is_same_v<decltype(--it), Iter&>);
68     auto& it_ref = --it;
69     assert(&it_ref == &it);
70 
71     assert(it == ++v.begin());
72 
73     static_assert(std::is_same_v<decltype(it--), Iter>);
74     auto tmp = it--;
75     assert(it == v.begin());
76     assert(tmp == ++v.begin());
77   }
78 
79   {
80     // non bidi
81     int buffer[3] = {4, 5, 6};
82     std::ranges::zip_view v(a, NonBidi{buffer});
83     using Iter = std::ranges::iterator_t<decltype(v)>;
84     static_assert(!canDecrement<Iter>);
85   }
86 
87   return true;
88 }
89 
main(int,char **)90 int main(int, char**) {
91   test();
92   static_assert(test());
93 
94   return 0;
95 }
96