brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.1 KiB · af14b51 Raw
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