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 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 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 156 int main(int, char**) { 157 test(); 158 static_assert(test()); 159 160 return 0; 161 } 162