xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/decrement.pass.cpp (revision 94461822c75d5080bf648f86552f7a59b76905c9)
1*94461822SHui Xie //===----------------------------------------------------------------------===//
2*94461822SHui Xie //
3*94461822SHui Xie // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*94461822SHui Xie // See https://llvm.org/LICENSE.txt for license information.
5*94461822SHui Xie // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*94461822SHui Xie //
7*94461822SHui Xie //===----------------------------------------------------------------------===//
8*94461822SHui Xie 
9*94461822SHui Xie // UNSUPPORTED: c++03, c++11, c++14, c++17
10*94461822SHui Xie 
11*94461822SHui Xie // constexpr iterator& operator--() requires bidirectional_range<Base>;
12*94461822SHui Xie // constexpr iterator operator--(int) requires bidirectional_range<Base>;
13*94461822SHui Xie 
14*94461822SHui Xie #include <array>
15*94461822SHui Xie #include <cassert>
16*94461822SHui Xie #include <ranges>
17*94461822SHui Xie #include <tuple>
18*94461822SHui Xie 
19*94461822SHui Xie #include "test_iterators.h"
20*94461822SHui Xie 
21*94461822SHui Xie template <class Iter>
22*94461822SHui Xie concept CanPreDecrement = requires(Iter it) { --it; };
23*94461822SHui Xie 
24*94461822SHui Xie template <class Iter>
25*94461822SHui Xie concept CanPostDecrement = requires(Iter it) { it--; };
26*94461822SHui Xie 
27*94461822SHui Xie template <class Iter, class Sent = sentinel_wrapper<Iter>>
testOne()28*94461822SHui Xie constexpr void testOne() {
29*94461822SHui Xie   using Range          = std::ranges::subrange<Iter, Sent>;
30*94461822SHui Xie   std::tuple<int> ts[] = {{1}, {2}, {3}};
31*94461822SHui Xie   auto ev              = Range{Iter{&ts[0]}, Sent{Iter{&ts[0] + 3}}} | std::views::elements<0>;
32*94461822SHui Xie 
33*94461822SHui Xie   using ElementIter = std::ranges::iterator_t<decltype(ev)>;
34*94461822SHui Xie 
35*94461822SHui Xie   if constexpr (!std::bidirectional_iterator<Iter>) {
36*94461822SHui Xie     auto it = ev.begin();
37*94461822SHui Xie     static_assert(!CanPreDecrement<decltype(it)>);
38*94461822SHui Xie     static_assert(!CanPostDecrement<decltype(it)>);
39*94461822SHui Xie   } else {
40*94461822SHui Xie     // --i
41*94461822SHui Xie     {
42*94461822SHui Xie       auto it = ev.begin();
43*94461822SHui Xie       static_assert(CanPreDecrement<decltype(it)>);
44*94461822SHui Xie 
45*94461822SHui Xie       ++it;
46*94461822SHui Xie       assert(base(it.base()) == &ts[1]);
47*94461822SHui Xie 
48*94461822SHui Xie       decltype(auto) result = --it;
49*94461822SHui Xie 
50*94461822SHui Xie       static_assert(std::is_same_v<decltype(result), ElementIter&>);
51*94461822SHui Xie       assert(&result == &it);
52*94461822SHui Xie 
53*94461822SHui Xie       assert(base(it.base()) == &ts[0]);
54*94461822SHui Xie     }
55*94461822SHui Xie 
56*94461822SHui Xie     // i--
57*94461822SHui Xie     {
58*94461822SHui Xie       auto it = ev.begin();
59*94461822SHui Xie       static_assert(CanPostDecrement<decltype(it)>);
60*94461822SHui Xie 
61*94461822SHui Xie       ++it;
62*94461822SHui Xie       assert(base(it.base()) == &ts[1]);
63*94461822SHui Xie 
64*94461822SHui Xie       decltype(auto) result = it--;
65*94461822SHui Xie 
66*94461822SHui Xie       static_assert(std::is_same_v<decltype(result), ElementIter>);
67*94461822SHui Xie 
68*94461822SHui Xie       assert(base(it.base()) == &ts[0]);
69*94461822SHui Xie       assert(base(result.base()) == &ts[1]);
70*94461822SHui Xie     }
71*94461822SHui Xie   }
72*94461822SHui Xie }
73*94461822SHui Xie 
test()74*94461822SHui Xie constexpr bool test() {
75*94461822SHui Xie   using Ptr = std::tuple<int>*;
76*94461822SHui Xie   testOne<cpp20_input_iterator<Ptr>>();
77*94461822SHui Xie   testOne<forward_iterator<Ptr>>();
78*94461822SHui Xie   testOne<bidirectional_iterator<Ptr>>();
79*94461822SHui Xie   testOne<random_access_iterator<Ptr>>();
80*94461822SHui Xie   testOne<contiguous_iterator<Ptr>>();
81*94461822SHui Xie   testOne<Ptr>();
82*94461822SHui Xie 
83*94461822SHui Xie   return true;
84*94461822SHui Xie }
85*94461822SHui Xie 
main(int,char **)86*94461822SHui Xie int main(int, char**) {
87*94461822SHui Xie   test();
88*94461822SHui Xie   static_assert(test());
89*94461822SHui Xie 
90*94461822SHui Xie   return 0;
91*94461822SHui Xie }
92