284 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// REQUIRES: std-at-least-c++2310 11// <ranges>12 13// constexpr iterator& operator--()14// requires ref-is-glvalue && bidirectional_range<Base> &&15// bidirectional-common<InnerBase> && bidirectional-common<PatternBase>;16// constexpr iterator operator--(int)17// requires ref-is-glvalue && bidirectional_range<Base> &&18// bidirectional-common<InnerBase> && bidirectional-common<PatternBase>;19 20#include <ranges>21 22#include <algorithm>23#include <array>24#include <cassert>25#include <forward_list>26#include <string>27#include <string_view>28#include <vector>29 30#include "../types.h"31 32template <class I>33concept CanPreDecrement = requires(I& i) {34 { --i } -> std::same_as<I&>;35};36 37template <class I>38concept CanPostDecrement = requires(I& i) {39 { i-- } -> std::same_as<I>;40};41 42template <class I>43concept CanDecrement = CanPreDecrement<I> && CanPostDecrement<I>;44 45constexpr bool test() {46 { // `V` and `Pattern` are not empty. Test return type too.47 using V = std::ranges::owning_view<std::vector<std::string>>;48 using Pattern = std::ranges::single_view<char>;49 using JWV = std::ranges::join_with_view<V, Pattern>;50 51 using Iter = std::ranges::iterator_t<JWV>;52 using CIter = std::ranges::iterator_t<const JWV>;53 static_assert(CanDecrement<Iter>);54 static_assert(CanDecrement<CIter>);55 56 JWV jwv(V{{"01", "23", "45"}}, Pattern{'_'});57 58 {59 auto it = jwv.end();60 std::same_as<Iter&> decltype(auto) it_ref = --it;61 assert(it_ref == it);62 assert(*it == '5');63 std::same_as<Iter> decltype(auto) it_copy = it--;64 assert(--it_copy == it);65 --it;66 assert(*it == '_');67 it--;68 assert(*it == '3');69 --it;70 it--;71 assert(*it == '_');72 }73 74 {75 auto cit = std::as_const(jwv).end();76 std::same_as<CIter&> decltype(auto) cit_ref = --cit;77 assert(cit_ref == cit);78 assert(*cit == '5');79 std::same_as<CIter> decltype(auto) cit_copy = cit--;80 assert(--cit_copy == cit);81 --cit;82 assert(*cit == '_');83 cit--;84 assert(*cit == '3');85 --cit;86 cit--;87 assert(*cit == '_');88 }89 90 assert(std::ranges::equal(std::views::reverse(std::move(jwv)), std::string_view{"54_32_10"}));91 }92 93 { // `Pattern` is empty, `V` is not.94 using Inner = std::array<int, 1>;95 using V = std::ranges::owning_view<std::array<Inner, 3>>;96 using Pattern = std::ranges::owning_view<std::array<int, 0>>;97 using JWV = std::ranges::join_with_view<V, Pattern>;98 99 JWV jwv(V{{Inner{-9}, Inner{-99}, Inner{-999}}}, Pattern{});100 101 {102 auto it = jwv.end();103 --it;104 assert(*it == -999);105 it--;106 assert(*it == -99);107 --it;108 assert(*it == -9);109 assert(it == jwv.begin());110 }111 112 {113 auto cit = std::as_const(jwv).end();114 --cit;115 assert(*cit == -999);116 cit--;117 assert(*cit == -99);118 --cit;119 assert(*cit == -9);120 assert(cit == std::as_const(jwv).begin());121 }122 }123 124#if !defined(TEST_COMPILER_GCC) // GCC c++/101777125 { // `V` has empty subrange in the middle, `Pattern` is not empty. Try to go back and forth.126 using V = std::array<std::vector<int>, 3>;127 using Pattern = std::ranges::single_view<int>;128 using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, Pattern>;129 130 JWV jwv(V{{{5}, {}, {125}}}, Pattern{1});131 132 {133 auto it = jwv.end();134 --it;135 assert(*it == 125);136 it--;137 assert(*it == 1);138 --it;139 assert(*it == 1);140 it--;141 assert(*it == 5);142 ++it;143 assert(*it == 1);144 --it;145 assert(*it == 5);146 std::ranges::advance(it, 4);147 it--;148 assert(*it == 125);149 }150 151 {152 auto cit = std::as_const(jwv).end();153 --cit;154 assert(*cit == 125);155 cit--;156 assert(*cit == 1);157 --cit;158 assert(*cit == 1);159 cit--;160 assert(*cit == 5);161 ++cit;162 assert(*cit == 1);163 --cit;164 assert(*cit == 5);165 std::ranges::advance(cit, 4);166 cit--;167 assert(*cit == 125);168 }169 }170 171 { // Only first element of `V` is not empty. `Pattern` is empty. Try to go back and forth.172 using Inner = std::vector<int>;173 using V = std::ranges::owning_view<std::array<Inner, 3>>;174 using Pattern = std::ranges::empty_view<int>;175 using JWV = std::ranges::join_with_view<V, Pattern>;176 177 JWV jwv(V{{Inner{999}, {}, {}}}, Pattern{});178 179 {180 auto it = jwv.end();181 --it;182 assert(*it == 999);183 ++it;184 assert(it == jwv.end());185 it--;186 assert(*it == 999);187 }188 189 {190 auto cit = std::as_const(jwv).end();191 --cit;192 assert(*cit == 999);193 ++cit;194 assert(cit == std::as_const(jwv).end());195 cit--;196 assert(*cit == 999);197 }198 }199#endif // !defined(TEST_COMPILER_GCC)200 201 { // `ref-is-glvalue` is false202 using V = RvalueVector<std::vector<int>>;203 using Pattern = std::ranges::empty_view<int>;204 using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>;205 using Iter = std::ranges::iterator_t<JWV>;206 static_assert(!CanPreDecrement<Iter>);207 static_assert(!CanPostDecrement<Iter>);208 }209 210 { // `Base` does not model bidirectional range211 using V = std::ranges::owning_view<std::forward_list<std::vector<int>>>;212 using Pattern = std::ranges::single_view<int>;213 using JWV = std::ranges::join_with_view<V, Pattern>;214 using Iter = std::ranges::iterator_t<JWV>;215 using CIter = std::ranges::iterator_t<const JWV>;216 static_assert(!CanPreDecrement<Iter>);217 static_assert(!CanPostDecrement<Iter>);218 static_assert(!CanPreDecrement<CIter>);219 static_assert(!CanPostDecrement<CIter>);220 }221 222 { // InnerBase does not model bidirectional-common223 { // InnerBase does not model bidirectional range224 using V = std::ranges::owning_view<std::vector<std::forward_list<int>>>;225 using Pattern = std::ranges::single_view<int>;226 using JWV = std::ranges::join_with_view<V, Pattern>;227 using Iter = std::ranges::iterator_t<JWV>;228 using CIter = std::ranges::iterator_t<const JWV>;229 static_assert(!CanPreDecrement<Iter>);230 static_assert(!CanPostDecrement<Iter>);231 static_assert(!CanPreDecrement<CIter>);232 static_assert(!CanPostDecrement<CIter>);233 }234 235 { // InnerBase does not model common range236 using InnerBase = BasicVectorView<int, ViewProperties{.common = false}, bidirectional_iterator>;237 using V = std::ranges::owning_view<std::vector<InnerBase>>;238 using Pattern = std::ranges::single_view<int>;239 using JWV = std::ranges::join_with_view<V, Pattern>;240 using Iter = std::ranges::iterator_t<JWV>;241 using CIter = std::ranges::iterator_t<const JWV>;242 static_assert(!CanPreDecrement<Iter>);243 static_assert(!CanPostDecrement<Iter>);244 static_assert(!CanPreDecrement<CIter>);245 static_assert(!CanPostDecrement<CIter>);246 }247 }248 249 { // PatternBase does not model bidirectional-common250 { // PatternBase does not model bidirectional range251 using V = std::ranges::owning_view<std::vector<std::vector<int>>>;252 using Pattern = std::ranges::owning_view<std::forward_list<int>>;253 using JWV = std::ranges::join_with_view<V, Pattern>;254 using Iter = std::ranges::iterator_t<JWV>;255 using CIter = std::ranges::iterator_t<const JWV>;256 static_assert(!CanPreDecrement<Iter>);257 static_assert(!CanPostDecrement<Iter>);258 static_assert(!CanPreDecrement<CIter>);259 static_assert(!CanPostDecrement<CIter>);260 }261 262 { // PatternBase does not model common range263 using V = std::ranges::owning_view<std::vector<std::vector<int>>>;264 using Pattern = BasicVectorView<int, ViewProperties{.common = false}, bidirectional_iterator>;265 using JWV = std::ranges::join_with_view<V, Pattern>;266 using Iter = std::ranges::iterator_t<JWV>;267 using CIter = std::ranges::iterator_t<const JWV>;268 static_assert(!CanPreDecrement<Iter>);269 static_assert(!CanPostDecrement<Iter>);270 static_assert(!CanPreDecrement<CIter>);271 static_assert(!CanPostDecrement<CIter>);272 }273 }274 275 return true;276}277 278int main(int, char**) {279 test();280 static_assert(test());281 282 return 0;283}284