373 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// constexpr void operator++(int);15// constexpr iterator operator++(int)16// requires ref-is-glvalue && forward_iterator<OuterIter> &&17// forward_iterator<InnerIter>;18 19#include <ranges>20 21#include <array>22#include <cassert>23#include <type_traits>24#include <vector>25 26#include "../types.h"27 28template <class I>29concept CanPreIncrement = requires(I& i) { ++i; };30 31template <class I>32concept CanPostIncrement = requires(I& i) { i++; };33 34template <bool RefIsGlvalue, class Inner>35using VRange = std::conditional_t<RefIsGlvalue, std::vector<Inner>, RvalueVector<Inner>>;36 37template <bool RefIsGlvalue>38constexpr void test_pre_increment() {39 { // `V` and `Pattern` are not empty. Test return type too.40 using V = VRange<RefIsGlvalue, std::array<int, 2>>;41 using Pattern = std::array<int, 2>;42 using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>;43 44 JWV jwv(V{{1, 1}, {2, 2}, {3, 3}}, Pattern{0, 0});45 46 {47 using Iter = std::ranges::iterator_t<JWV>;48 static_assert(CanPreIncrement<Iter>);49 static_assert(!CanPreIncrement<const Iter>);50 51 auto it = jwv.begin();52 assert(*it == 1);53 std::same_as<Iter&> decltype(auto) it_ref = ++it;54 if constexpr (RefIsGlvalue) {55 assert(it_ref == it);56 }57 58 ++it;59 assert(*it == 0);60 ++it_ref;61 ++it_ref;62 assert(*it_ref == 2);63 ++it;64 ++it_ref;65 assert(*it == 0);66 }67 68 if constexpr (RefIsGlvalue) {69 using CIter = std::ranges::iterator_t<const JWV>;70 static_assert(CanPreIncrement<CIter>);71 static_assert(!CanPreIncrement<const CIter>);72 73 auto cit = std::as_const(jwv).begin();74 assert(*cit == 1);75 std::same_as<CIter&> decltype(auto) cit_ref = ++cit;76 assert(cit_ref == cit);77 ++cit;78 assert(*cit == 0);79 ++cit_ref;80 ++cit_ref;81 assert(*cit_ref == 2);82 ++cit;83 ++cit_ref;84 assert(*cit == 0);85 }86 }87 88 { // `V` and `Pattern` are empty.89 using V = VRange<RefIsGlvalue, std::ranges::empty_view<int>>;90 using Pattern = std::ranges::empty_view<int>;91 using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>;92 93 JWV jwv = {};94 95 {96 auto it = jwv.begin();97 assert(it == jwv.end());98 }99 100 if constexpr (RefIsGlvalue) {101 auto cit = std::as_const(jwv).begin();102 assert(cit == std::as_const(jwv).end());103 }104 }105 106 { // `Pattern` is empty, `V` is not.107 using V = VRange<RefIsGlvalue, std::vector<int>>;108 using Pattern = std::vector<int>;109 using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>;110 111 JWV jwv(V{{{-1}, {-2}, {-3}}}, Pattern{});112 113 {114 auto it = jwv.begin();115 assert(*it == -1);116 ++it;117 assert(*it == -2);118 ++it;119 assert(*it == -3);120 ++it;121 assert(it == jwv.end());122 }123 124 if constexpr (RefIsGlvalue) {125 auto cit = std::as_const(jwv).begin();126 assert(*cit == -1);127 ++cit;128 assert(*cit == -2);129 ++cit;130 assert(*cit == -3);131 ++cit;132 assert(cit == std::as_const(jwv).end());133 }134 }135 136 { // `V` has empty subrange in the middle, `Pattern` is not empty.137 using V = VRange<RefIsGlvalue, std::vector<int>>;138 using Pattern = std::ranges::single_view<int>;139 using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, Pattern>;140 141 JWV jwv(V{{1}, {}, {3}}, Pattern{0});142 143 {144 auto it = jwv.begin();145 assert(*it == 1);146 ++it;147 assert(*it == 0);148 ++it;149 assert(*it == 0);150 ++it;151 assert(*it == 3);152 }153 154 if constexpr (RefIsGlvalue) {155 auto cit = std::as_const(jwv).begin();156 assert(*cit == 1);157 ++cit;158 assert(*cit == 0);159 ++cit;160 assert(*cit == 0);161 ++cit;162 assert(*cit == 3);163 }164 }165 166 { // Only last element of `V` is not empty. `Pattern` is not empty.167 using V = VRange<RefIsGlvalue, std::vector<int>>;168 using Pattern = std::ranges::single_view<int>;169 using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, Pattern>;170 171 JWV jwv(V{{}, {}, {555}}, Pattern{1});172 173 {174 auto it = jwv.begin();175 assert(*it == 1);176 ++it;177 assert(*it == 1);178 ++it;179 assert(*it == 555);180 ++it;181 assert(it == jwv.end());182 }183 184 if constexpr (RefIsGlvalue) {185 auto cit = std::as_const(jwv).begin();186 assert(*cit == 1);187 ++cit;188 assert(*cit == 1);189 ++cit;190 assert(*cit == 555);191 ++cit;192 assert(cit == std::as_const(jwv).end());193 }194 }195 196 { // Only first element of `V` is not empty. `Pattern` is empty.197 using V = VRange<RefIsGlvalue, std::vector<int>>;198 using Pattern = std::ranges::empty_view<int>;199 using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, Pattern>;200 201 JWV jwv(V{{777}, {}, {}}, Pattern{});202 203 {204 auto it = jwv.begin();205 assert(*it == 777);206 ++it;207 assert(it == jwv.end());208 }209 210 if constexpr (RefIsGlvalue) {211 auto cit = std::as_const(jwv).begin();212 assert(*cit == 777);213 ++cit;214 assert(cit == std::as_const(jwv).end());215 }216 }217 218 { // Only last element of `V` is not empty. `Pattern` is empty. `V` models input range.219 using V = BasicView<VRange<RefIsGlvalue, std::string>, ViewProperties{}, DefaultCtorInputIter>;220 using Pattern = std::ranges::empty_view<char>;221 using JWV = std::ranges::join_with_view<V, Pattern>;222 223 JWV jwv(V{{}, {}, {'a'}}, Pattern{});224 225 auto it = jwv.begin();226 assert(*it == 'a');227 ++it;228 assert(it == jwv.end());229 }230 231 { // Only first element of `V` is not empty. `Pattern` is not empty. `V` models input range.232 using V = BasicView<VRange<RefIsGlvalue, std::string>, ViewProperties{}, DefaultCtorInputIter>;233 using Pattern = std::ranges::single_view<char>;234 using JWV = std::ranges::join_with_view<V, Pattern>;235 236 JWV jwv(V{{'b'}, {}, {}}, Pattern{'.'});237 238 auto it = jwv.begin();239 assert(*it == 'b');240 ++it;241 assert(*it == '.');242 ++it;243 assert(*it == '.');244 ++it;245 assert(it == jwv.end());246 }247}248 249constexpr void test_post_increment() {250 { // `V` and `Pattern` are not empty. Return type should be `iterator`.251 using V = std::array<std::array<int, 3>, 2>;252 using Pattern = std::array<int, 1>;253 using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>;254 255 using Iter = std::ranges::iterator_t<JWV>;256 using CIter = std::ranges::iterator_t<const JWV>;257 static_assert(CanPostIncrement<Iter>);258 static_assert(!CanPostIncrement<const Iter>);259 static_assert(CanPostIncrement<CIter>);260 static_assert(!CanPostIncrement<const CIter>);261 262 JWV jwv(V{{{6, 5, 4}, {3, 2, 1}}}, Pattern{-5});263 264 {265 auto it = jwv.begin();266 assert(*it == 6);267 std::same_as<Iter> decltype(auto) it_copy = it++;268 assert(++it_copy == it);269 it++;270 it++;271 assert(*it == -5);272 it_copy++;273 it_copy++;274 assert(*it_copy == -5);275 it++;276 it_copy++;277 assert(*it == 3);278 assert(*it_copy == 3);279 }280 281 {282 auto cit = std::as_const(jwv).begin();283 assert(*cit == 6);284 std::same_as<CIter> decltype(auto) cit_copy = cit++;285 assert(++cit_copy == cit);286 cit++;287 cit++;288 assert(*cit == -5);289 cit_copy++;290 cit_copy++;291 assert(*cit_copy == -5);292 cit++;293 cit_copy++;294 assert(*cit == 3);295 assert(*cit_copy == 3);296 }297 }298 299 { // `Pattern` is empty, `V` is not. Value of `ref-is-glvalue` is false (return type should be `void`).300 using Inner = std::vector<int>;301 using V = RvalueVector<Inner>;302 using Pattern = std::ranges::empty_view<int>;303 using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>;304 305 JWV jwv(V{Inner{-3}, Inner{-2}, Inner{-1}}, Pattern{});306 307 auto it = jwv.begin();308 assert(*it == -3);309 it++;310 assert(*it == -2);311 it++;312 assert(*it == -1);313 it++;314 assert(it == jwv.end());315 static_assert(std::is_void_v<decltype(it++)>);316 }317 318 { // `V` has empty subrange in the middle, `Pattern` is not empty.319 // OuterIter does not model forward iterator (return type should be `void`).320 using Inner = std::vector<int>;321 using V = BasicVectorView<Inner, ViewProperties{.common = false}, cpp20_input_iterator>;322 using Pattern = std::ranges::single_view<int>;323 using JWV = std::ranges::join_with_view<V, Pattern>;324 325 JWV jwv(V{Inner{7}, {}, Inner{9}}, Pattern{8});326 327 auto it = jwv.begin();328 assert(*it == 7);329 it++;330 assert(*it == 8);331 it++;332 assert(*it == 8);333 it++;334 assert(*it == 9);335 it++;336 assert(it == jwv.end());337 static_assert(std::is_void_v<decltype(it++)>);338 }339 340#if !defined(TEST_COMPILER_GCC) // GCC c++/101777341 { // Only first element of `V` is not empty. `Pattern` is empty. InnerIter does not model forward342 // iterator (return type should be `void`).343 using Inner = BasicVectorView<char32_t, ViewProperties{.common = false}, cpp17_input_iterator>;344 using V = std::array<Inner, 3>;345 using Pattern = std::ranges::empty_view<char32_t>;346 using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, Pattern>;347 348 JWV jwv(V{Inner{U'?'}, Inner{}, Inner{}}, Pattern{});349 350 auto it = jwv.begin();351 assert(*it == U'?');352 it++;353 assert(it == jwv.end());354 static_assert(std::is_void_v<decltype(it++)>);355 }356#endif // !defined(TEST_COMPILER_GCC)357}358 359constexpr bool test() {360 test_pre_increment<false>();361 test_pre_increment<true>();362 test_post_increment();363 364 return true;365}366 367int main(int, char**) {368 test();369 static_assert(test());370 371 return 0;372}373