222 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 auto begin();14// constexpr auto begin() const15// requires forward_range<const V> &&16// forward_range<const Pattern> &&17// is_reference_v<range_reference_t<const V>> &&18// input_range<range_reference_t<const V>>;19 20#include <ranges>21 22#include <algorithm>23#include <array>24#include <string>25#include <vector>26 27#include "../types.h"28#include "test_iterators.h"29 30template <bool Simple>31using MaybeSimpleForwardView = BasicView<std::vector<std::string>, ViewProperties{.simple = Simple}, forward_iterator>;32 33template <bool Simple>34using MaybeSimpleForwardRvalueView =35 BasicView<RvalueVector<std::string>, ViewProperties{.simple = Simple}, forward_iterator>;36 37template <bool Simple>38using MaybeSimplePattern = BasicView<std::string, ViewProperties{.simple = Simple}, forward_iterator>;39 40template <class V, class Pattern>41concept JoinWithViewHasConstBegin = requires(const std::ranges::join_with_view<V, Pattern> jwv) {42 { jwv.begin() } -> std::input_iterator;43};44 45constexpr void test_begin() {46 using Str = std::string;47 using Vec = std::vector<Str>;48 49 { // `V` models simple-view50 // `is_reference_v<InnerRng>` is true51 // `Pattern` models simple-view52 // `V` and `Pattern` contain some elements53 using V = MaybeSimpleForwardView<true>;54 using Pattern = MaybeSimplePattern<true>;55 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{"A", "B", "C"}), Pattern(Str{">>"}));56 auto it = jwv.begin();57 assert(std::ranges::equal(std::views::counted(it, 7), Str{"A>>B>>C"}));58 }59 60 { // `V` does not model simple-view61 // `is_reference_v<InnerRng>` is true62 // `Pattern` models simple-view63 // `V` and `Pattern` are empty64 using V = MaybeSimpleForwardView<false>;65 using Pattern = MaybeSimplePattern<true>;66 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{}), Pattern(Str{}));67 auto it = jwv.begin();68 assert(it == jwv.end());69 }70 71 { // `V` models simple-view72 // `is_reference_v<InnerRng>` is false73 // `Pattern` models simple-view74 // `V` contains two elements, `Pattern` is empty75 using V = MaybeSimpleForwardRvalueView<true>;76 using Pattern = MaybeSimplePattern<true>;77 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{"1", "2"}), Pattern(Str{""}));78 auto it = jwv.begin();79 assert(*it == '1');80 assert(*++it == '2');81 }82 83 { // `V` models simple-view84 // `is_reference_v<InnerRng>` is true85 // `Pattern` does not model simple-view86 // `V` contains one element, `Pattern` is empty87 using V = MaybeSimpleForwardView<true>;88 using Pattern = MaybeSimplePattern<false>;89 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{"07"}), Pattern(Str{}));90 auto it = jwv.begin();91 assert(*it++ == '0');92 assert(*it == '7');93 }94 95 { // `V` does not model simple-view96 // `is_reference_v<InnerRng>` is false97 // `Pattern` models simple-view98 // `V` contains three elements (2nd is empty), `Pattern` is not empty99 using V = MaybeSimpleForwardRvalueView<false>;100 using Pattern = MaybeSimplePattern<true>;101 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{"A", "", "C"}), Pattern(Str{"--"}));102 auto it = jwv.begin();103 assert(std::ranges::equal(std::views::counted(it, 6), Str("A----C")));104 }105 106 { // `V` does not model simple-view107 // `is_reference_v<InnerRng>` is true108 // `Pattern` does not model simple-view109 // `V` contains some empty elements, `Pattern` is not empty110 using V = MaybeSimpleForwardView<false>;111 using Pattern = MaybeSimplePattern<false>;112 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{"", "", ""}), Pattern(Str{"-"}));113 auto it = jwv.begin();114 assert(*it++ == '-');115 assert(*it == '-');116 }117 118 { // `V` models simple-view119 // `is_reference_v<InnerRng>` is false120 // `Pattern` does not model simple-view121 // `V` contains two elements, `Pattern` is not empty122 using V = MaybeSimpleForwardRvalueView<true>;123 using Pattern = MaybeSimplePattern<false>;124 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{"X", "Z"}), Pattern(Str{"Y"}));125 auto it = jwv.begin();126 assert(*it == 'X');127 assert(*++it == 'Y');128 assert(*++it == 'Z');129 }130 131 { // `V` does not model simple-view132 // `is_reference_v<InnerRng>` is false133 // `Pattern` does not model simple-view134 // `V` contains two empty elements, `Pattern` is not empty135 using V = MaybeSimpleForwardRvalueView<false>;136 using Pattern = MaybeSimplePattern<false>;137 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{"", ""}), Pattern(Str{"?"}));138 auto it = jwv.begin();139 assert(*it == '?');140 assert(++it == jwv.end());141 }142 143 { // `V` does not model forward range144 // `V` contains some empty elements, `Pattern` is empty145 using V = BasicView<Vec, ViewProperties{.common = false}, cpp20_input_iterator>;146 using Pattern = MaybeSimplePattern<false>;147 std::ranges::join_with_view<V, Pattern> jwv(V(Vec{"", "", ""}), Pattern(Str{""}));148 auto it = jwv.begin();149 assert(it == jwv.end());150 }151}152 153constexpr void test_const_begin() {154 using Vec = std::vector<std::array<int, 2>>;155 using Pat = std::array<int, 2>;156 157 { // `const V` models forward range158 // `const Pattern` models forward range159 // `is_reference_v<range_reference_t<const V>>` is true160 // `range_reference_t<const V>` models input range161 using V = BasicView<Vec, ViewProperties{}, forward_iterator>;162 using Pattern = BasicView<Pat, ViewProperties{}, forward_iterator>;163 164 const std::ranges::join_with_view<V, Pattern> jwv{V{Vec{std::array{1, 2}, std::array{3, 4}}}, Pattern{Pat{0, 0}}};165 auto it = jwv.begin();166 assert(std::ranges::equal(std::views::counted(it, 6), std::array{1, 2, 0, 0, 3, 4}));167 }168 169 // `const V` does not model forward range170 // `const Pattern` models forward range171 // `is_reference_v<range_reference_t<const V>>` is true172 // `range_reference_t<const V>` models input range173 static_assert(!JoinWithViewHasConstBegin<BasicView<Vec, ViewProperties{.common = false}, cpp20_input_iterator>,174 BasicView<Pat, ViewProperties{}, forward_iterator>>);175 176 // `const V` models forward range177 // `const Pattern` does not model forward range178 // `is_reference_v<range_reference_t<const V>>` is true179 // `range_reference_t<const V>` models input range180 static_assert(!JoinWithViewHasConstBegin<BasicView<Vec, ViewProperties{}, forward_iterator>,181 BasicView<Pat, ViewProperties{.common = false}, cpp20_input_iterator>>);182 183 // `const V` models forward range184 // `const Pattern` models forward range185 // `is_reference_v<range_reference_t<const V>>` is false186 // `range_reference_t<const V>` models input range187 static_assert(188 !JoinWithViewHasConstBegin<BasicView<RvalueVector<std::vector<int>>, ViewProperties{}, forward_iterator>,189 BasicView<Pat, ViewProperties{}, forward_iterator>>);190 191 // `const V` models forward range192 // `const Pattern` models forward range193 // `is_reference_v<range_reference_t<const V>>` is true194 // `range_reference_t<const V>` does not model input range195 static_assert(!JoinWithViewHasConstBegin<196 BasicView<std::vector<InputRangeButOutputWhenConst<int>>, ViewProperties{}, forward_iterator>,197 BasicView<Pat, ViewProperties{}, forward_iterator>>);198 199 // `concatable<range_reference_t<const V>, const Pattern>` is not satisfied200 // See also LWG-4074: compatible-joinable-ranges is underconstrained201 static_assert(!JoinWithViewHasConstBegin<BasicVectorView<int, ViewProperties{}, forward_iterator>,202 lwg4074::PatternWithProxyConstAccess>);203 204 // Check situation when iterators returned by `begin()` and `begin() const` are the same205 using JWV = std::ranges::join_with_view<MaybeSimpleForwardView<true>, MaybeSimplePattern<true>>;206 static_assert(std::same_as<std::ranges::iterator_t<JWV&>, std::ranges::iterator_t<const JWV&>>);207}208 209constexpr bool test() {210 test_begin();211 test_const_begin();212 213 return true;214}215 216int main(int, char**) {217 test();218 static_assert(test());219 220 return 0;221}222