201 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// UNSUPPORTED: c++03, c++11, c++14, c++1710 11// friend constexpr bool operator==(const iterator_t<Base>& x, const sentinel& y);12//13// template<bool OtherConst = !Const>14// requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>15// friend constexpr bool operator==(const iterator_t<maybe-const<OtherConst, V>>& x,16// const sentinel& y);17 18#include <array>19#include <cassert>20#include <ranges>21 22#include "../types.h"23 24template <bool Const>25struct Iter {26 int* it_;27 28 using value_type = int;29 using difference_type = std::intptr_t;30 using iterator_concept = std::input_iterator_tag;31 32 constexpr decltype(auto) operator*() const { return *it_; }33 constexpr Iter& operator++() {34 ++it_;35 return *this;36 }37 constexpr void operator++(int) { ++it_; }38};39 40template <bool Const>41struct Sent {42 int* end_;43 44 constexpr bool operator==(const Iter<Const>& i) const { return i.it_ == end_; }45};46 47template <bool Const>48struct CrossComparableSent {49 int* end_;50 51 template <bool C>52 constexpr bool operator==(const Iter<C>& i) const {53 return i.it_ == end_;54 }55};56 57template <template <bool> typename St>58struct Range : IntBufferViewBase {59 using IntBufferViewBase::IntBufferViewBase;60 constexpr Iter<false> begin() { return Iter<false>{buffer_}; }61 constexpr Iter<true> begin() const { return Iter<true>{buffer_}; }62 constexpr St<false> end() { return St<false>{buffer_ + size_}; }63 constexpr St<true> end() const { return St<true>{buffer_ + size_}; }64};65 66using R = Range<Sent>;67using CrossComparableR = Range<CrossComparableSent>;68 69struct LessThan3 {70 constexpr bool operator()(int i) const { return i < 3; }71};72 73using std::ranges::iterator_t;74using std::ranges::sentinel_t;75using std::ranges::take_while_view;76 77static_assert(weakly_equality_comparable_with<iterator_t<take_while_view<R, LessThan3>>, //78 sentinel_t<take_while_view<R, LessThan3>>>);79 80static_assert(!weakly_equality_comparable_with<iterator_t<const take_while_view<R, LessThan3>>, //81 sentinel_t<take_while_view<R, LessThan3>>>);82 83static_assert(!weakly_equality_comparable_with<iterator_t<take_while_view<R, LessThan3>>, //84 sentinel_t<const take_while_view<R, LessThan3>>>);85 86static_assert(weakly_equality_comparable_with<iterator_t<const take_while_view<R, LessThan3>>, //87 sentinel_t<const take_while_view<R, LessThan3>>>);88 89static_assert(weakly_equality_comparable_with<iterator_t<take_while_view<CrossComparableR, LessThan3>>, //90 sentinel_t<take_while_view<CrossComparableR, LessThan3>>>);91 92static_assert(weakly_equality_comparable_with<iterator_t<const take_while_view<CrossComparableR, LessThan3>>, //93 sentinel_t<take_while_view<CrossComparableR, LessThan3>>>);94 95static_assert(weakly_equality_comparable_with<iterator_t<take_while_view<CrossComparableR, LessThan3>>, //96 sentinel_t<const take_while_view<CrossComparableR, LessThan3>>>);97 98static_assert(weakly_equality_comparable_with<iterator_t<const take_while_view<CrossComparableR, LessThan3>>, //99 sentinel_t<const take_while_view<CrossComparableR, LessThan3>>>);100 101template <class R, bool ConstIter, bool ConstSent>102constexpr void testOne() {103 auto getBegin = [](auto&& rng) {104 if constexpr (ConstIter) {105 return std::as_const(rng).begin();106 } else {107 return rng.begin();108 }109 };110 111 auto getEnd = [](auto&& rng) {112 if constexpr (ConstSent) {113 return std::as_const(rng).end();114 } else {115 return rng.end();116 }117 };118 119 // iter == sentinel.base120 {121 int buffer[] = {1};122 R v{buffer};123 std::ranges::take_while_view twv(v, LessThan3{});124 auto iter = getBegin(twv);125 auto st = getEnd(twv);126 ++iter;127 assert(iter == st);128 }129 130 // iter != sentinel.base && pred(*iter)131 {132 int buffer[] = {1, 3, 4};133 R v{buffer};134 std::ranges::take_while_view twv(v, LessThan3{});135 auto iter = getBegin(twv);136 auto st = getEnd(twv);137 assert(iter != st);138 ++iter;139 assert(iter == st);140 }141 142 // iter != sentinel.base && !pred(*iter)143 {144 int buffer[] = {1, 2, 3, 4, 3, 2, 1};145 R v{buffer};146 std::ranges::take_while_view twv(v, LessThan3{});147 auto iter = getBegin(twv);148 auto sent = getEnd(twv);149 assert(iter != sent);150 }151 152 // empty range153 {154 std::array<int, 0> arr;155 R v{arr};156 std::ranges::take_while_view twv(v, LessThan3{});157 auto iter = getBegin(twv);158 auto sent = getEnd(twv);159 assert(iter == sent);160 }161}162 163constexpr bool test() {164 testOne<R, false, false>();165 testOne<R, true, true>();166 testOne<CrossComparableR, false, false>();167 testOne<CrossComparableR, true, true>();168 169 // LWG 3449 `take_view` and `take_while_view`'s `sentinel<false>` not comparable with their const iterator170 testOne<CrossComparableR, true, false>();171 testOne<CrossComparableR, false, true>();172 173 // test std::invoke is used174 {175 struct Data {176 bool b;177 };178 179 Data buffer[] = {{true}, {true}, {false}};180 std::ranges::take_while_view twv(buffer, &Data::b);181 auto it = twv.begin();182 auto st = twv.end();183 assert(it != st);184 185 ++it;186 assert(it != st);187 188 ++it;189 assert(it == st);190 }191 192 return true;193}194 195int main(int, char**) {196 test();197 static_assert(test());198 199 return 0;200}201