194461822SHui Xie //===----------------------------------------------------------------------===//
294461822SHui Xie //
394461822SHui Xie // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
494461822SHui Xie // See https://llvm.org/LICENSE.txt for license information.
594461822SHui Xie // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
694461822SHui Xie //
794461822SHui Xie //===----------------------------------------------------------------------===//
894461822SHui Xie
994461822SHui Xie // UNSUPPORTED: c++03, c++11, c++14, c++17
1094461822SHui Xie
1194461822SHui Xie // template<bool OtherConst>
1294461822SHui Xie // requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
1394461822SHui Xie // friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
1494461822SHui Xie
1594461822SHui Xie #include <array>
1694461822SHui Xie #include <cassert>
1794461822SHui Xie #include <ranges>
1894461822SHui Xie
1994461822SHui Xie #include "../types.h"
20*808d794aSWill Hawkins #include "test_range.h"
2194461822SHui Xie
2294461822SHui Xie template <bool Const>
2394461822SHui Xie struct Iter {
2494461822SHui Xie std::tuple<int>* it_;
2594461822SHui Xie
2694461822SHui Xie using value_type = std::tuple<int>;
27d59a43feSMark de Wever using difference_type = std::intptr_t;
2894461822SHui Xie using iterator_concept = std::input_iterator_tag;
2994461822SHui Xie
operator *Iter3094461822SHui Xie constexpr decltype(auto) operator*() const { return *it_; }
operator ++Iter3194461822SHui Xie constexpr Iter& operator++() {
3294461822SHui Xie ++it_;
3394461822SHui Xie return *this;
3494461822SHui Xie }
operator ++Iter3594461822SHui Xie constexpr void operator++(int) { ++it_; }
3694461822SHui Xie };
3794461822SHui Xie
3894461822SHui Xie template <bool Const>
3994461822SHui Xie struct Sent {
4094461822SHui Xie std::tuple<int>* end_;
4194461822SHui Xie
operator ==Sent4294461822SHui Xie constexpr bool operator==(const Iter<Const>& i) const { return i.it_ == end_; }
4394461822SHui Xie };
4494461822SHui Xie
4594461822SHui Xie template <bool Const>
4694461822SHui Xie struct CrossComparableSent {
4794461822SHui Xie std::tuple<int>* end_;
4894461822SHui Xie
4994461822SHui Xie template <bool C>
operator ==CrossComparableSent5094461822SHui Xie constexpr bool operator==(const Iter<C>& i) const {
5194461822SHui Xie return i.it_ == end_;
5294461822SHui Xie }
5394461822SHui Xie };
5494461822SHui Xie
5594461822SHui Xie template <template <bool> typename St>
5694461822SHui Xie struct Range : TupleBufferView {
5794461822SHui Xie using TupleBufferView::TupleBufferView;
beginRange5894461822SHui Xie constexpr Iter<false> begin() { return Iter<false>{buffer_}; }
beginRange5994461822SHui Xie constexpr Iter<true> begin() const { return Iter<true>{buffer_}; }
endRange6094461822SHui Xie constexpr St<false> end() { return St<false>{buffer_ + size_}; }
endRange6194461822SHui Xie constexpr St<true> end() const { return St<true>{buffer_ + size_}; }
6294461822SHui Xie };
6394461822SHui Xie
6494461822SHui Xie using R = Range<Sent>;
6594461822SHui Xie using CrossComparableR = Range<CrossComparableSent>;
6694461822SHui Xie
6794461822SHui Xie using std::ranges::elements_view;
6894461822SHui Xie using std::ranges::iterator_t;
6994461822SHui Xie using std::ranges::sentinel_t;
7094461822SHui Xie
71*808d794aSWill Hawkins static_assert(weakly_equality_comparable_with<iterator_t<elements_view<R, 0>>, //
7294461822SHui Xie sentinel_t<elements_view<R, 0>>>);
7394461822SHui Xie
74*808d794aSWill Hawkins static_assert(!weakly_equality_comparable_with<iterator_t<const elements_view<R, 0>>, //
7594461822SHui Xie sentinel_t<elements_view<R, 0>>>);
7694461822SHui Xie
77*808d794aSWill Hawkins static_assert(!weakly_equality_comparable_with<iterator_t<elements_view<R, 0>>, //
7894461822SHui Xie sentinel_t<const elements_view<R, 0>>>);
7994461822SHui Xie
80*808d794aSWill Hawkins static_assert(weakly_equality_comparable_with<iterator_t<const elements_view<R, 0>>, //
8194461822SHui Xie sentinel_t<const elements_view<R, 0>>>);
8294461822SHui Xie
83*808d794aSWill Hawkins static_assert(weakly_equality_comparable_with<iterator_t<elements_view<CrossComparableR, 0>>, //
8494461822SHui Xie sentinel_t<elements_view<CrossComparableR, 0>>>);
8594461822SHui Xie
86*808d794aSWill Hawkins static_assert(weakly_equality_comparable_with<iterator_t<const elements_view<CrossComparableR, 0>>, //
87*808d794aSWill Hawkins sentinel_t<elements_view<CrossComparableR, 0>>>);
88*808d794aSWill Hawkins
89*808d794aSWill Hawkins static_assert(weakly_equality_comparable_with<iterator_t<elements_view<CrossComparableR, 0>>, //
9094461822SHui Xie sentinel_t<const elements_view<CrossComparableR, 0>>>);
9194461822SHui Xie
92*808d794aSWill Hawkins static_assert(weakly_equality_comparable_with<iterator_t<const elements_view<CrossComparableR, 0>>, //
9394461822SHui Xie sentinel_t<const elements_view<CrossComparableR, 0>>>);
9494461822SHui Xie
9594461822SHui Xie template <class R, bool ConstIter, bool ConstSent>
testOne()9694461822SHui Xie constexpr void testOne() {
9794461822SHui Xie auto getBegin = [](auto&& rng) {
9894461822SHui Xie if constexpr (ConstIter) {
9994461822SHui Xie return std::as_const(rng).begin();
10094461822SHui Xie } else {
10194461822SHui Xie return rng.begin();
10294461822SHui Xie }
10394461822SHui Xie };
10494461822SHui Xie
10594461822SHui Xie auto getEnd = [](auto&& rng) {
10694461822SHui Xie if constexpr (ConstSent) {
10794461822SHui Xie return std::as_const(rng).end();
10894461822SHui Xie } else {
10994461822SHui Xie return rng.end();
11094461822SHui Xie }
11194461822SHui Xie };
11294461822SHui Xie
11394461822SHui Xie // iter == sentinel.base
11494461822SHui Xie {
11594461822SHui Xie std::tuple<int> buffer[] = {{1}};
11694461822SHui Xie R v{buffer};
11794461822SHui Xie std::ranges::elements_view<R, 0> ev(v);
11894461822SHui Xie auto iter = getBegin(ev);
11994461822SHui Xie auto st = getEnd(ev);
12094461822SHui Xie ++iter;
12194461822SHui Xie assert(iter == st);
12294461822SHui Xie }
12394461822SHui Xie
12494461822SHui Xie // iter != sentinel.base
12594461822SHui Xie {
12694461822SHui Xie std::tuple<int> buffer[] = {{1}};
12794461822SHui Xie R v{buffer};
12894461822SHui Xie std::ranges::elements_view<R, 0> ev(v);
12994461822SHui Xie auto iter = getBegin(ev);
13094461822SHui Xie auto st = getEnd(ev);
13194461822SHui Xie assert(iter != st);
13294461822SHui Xie }
13394461822SHui Xie
13494461822SHui Xie // empty range
13594461822SHui Xie {
13694461822SHui Xie std::array<std::tuple<int>, 0> arr;
13794461822SHui Xie R v{arr};
13894461822SHui Xie std::ranges::elements_view<R, 0> ev(v);
13994461822SHui Xie auto iter = getBegin(ev);
14094461822SHui Xie auto sent = getEnd(ev);
14194461822SHui Xie assert(iter == sent);
14294461822SHui Xie }
14394461822SHui Xie }
14494461822SHui Xie
test()14594461822SHui Xie constexpr bool test() {
14694461822SHui Xie testOne<R, false, false>();
14794461822SHui Xie testOne<R, true, true>();
14894461822SHui Xie testOne<CrossComparableR, false, false>();
14994461822SHui Xie testOne<CrossComparableR, true, true>();
15094461822SHui Xie testOne<CrossComparableR, true, false>();
15194461822SHui Xie testOne<CrossComparableR, false, true>();
15294461822SHui Xie
15394461822SHui Xie return true;
15494461822SHui Xie }
15594461822SHui Xie
main(int,char **)15694461822SHui Xie int main(int, char**) {
15794461822SHui Xie test();
15894461822SHui Xie static_assert(test());
15994461822SHui Xie
16094461822SHui Xie return 0;
16194461822SHui Xie }
162