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 sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
1394461822SHui Xie // friend constexpr range_difference_t<maybe-const<OtherConst, V>>
1494461822SHui Xie // operator-(const iterator<OtherConst>& x, const sentinel& y);
1594461822SHui Xie //
1694461822SHui Xie // template<bool OtherConst>
1794461822SHui Xie // requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
1894461822SHui Xie // friend constexpr range_difference_t<maybe-const<OtherConst, V>>
1994461822SHui Xie // operator-(const sentinel& x, const iterator<OtherConst>& y);
2094461822SHui Xie
2194461822SHui Xie #include <cassert>
2294461822SHui Xie #include <concepts>
23*3fe3f9c5SKonstantin Varlamov #include <cstddef>
2494461822SHui Xie #include <functional>
2594461822SHui Xie #include <ranges>
2694461822SHui Xie #include <tuple>
2794461822SHui Xie
2894461822SHui Xie #include "../types.h"
2994461822SHui Xie
3094461822SHui Xie template <bool Const>
3194461822SHui Xie struct Iter {
3294461822SHui Xie std::tuple<int>* it_;
3394461822SHui Xie
3494461822SHui Xie using value_type = std::tuple<int>;
35*3fe3f9c5SKonstantin Varlamov using difference_type = std::ptrdiff_t;
3694461822SHui Xie using iterator_concept = std::input_iterator_tag;
3794461822SHui Xie
operator *Iter3894461822SHui Xie constexpr decltype(auto) operator*() const { return *it_; }
operator ++Iter3994461822SHui Xie constexpr Iter& operator++() {
4094461822SHui Xie ++it_;
4194461822SHui Xie return *this;
4294461822SHui Xie }
operator ++Iter4394461822SHui Xie constexpr void operator++(int) { ++it_; }
4494461822SHui Xie };
4594461822SHui Xie
4694461822SHui Xie template <bool Const>
4794461822SHui Xie struct Sent {
4894461822SHui Xie std::tuple<int>* end_;
4994461822SHui Xie
operator ==Sent5094461822SHui Xie constexpr bool operator==(const Iter<Const>& i) const { return i.it_ == end_; }
5194461822SHui Xie };
5294461822SHui Xie
5394461822SHui Xie template <bool Const>
5494461822SHui Xie struct SizedSent {
5594461822SHui Xie std::tuple<int>* end_;
5694461822SHui Xie
operator ==SizedSent5794461822SHui Xie constexpr bool operator==(const Iter<Const>& i) const { return i.it_ == end_; }
5894461822SHui Xie
operator -(const SizedSent & st,const Iter<Const> & it)5994461822SHui Xie friend constexpr auto operator-(const SizedSent& st, const Iter<Const>& it) { return st.end_ - it.it_; }
6094461822SHui Xie
operator -(const Iter<Const> & it,const SizedSent & st)6194461822SHui Xie friend constexpr auto operator-(const Iter<Const>& it, const SizedSent& st) { return it.it_ - st.end_; }
6294461822SHui Xie };
6394461822SHui Xie
6494461822SHui Xie template <bool Const>
6594461822SHui Xie struct CrossSizedSent {
6694461822SHui Xie std::tuple<int>* end_;
6794461822SHui Xie
6894461822SHui Xie template <bool C>
operator ==CrossSizedSent6994461822SHui Xie constexpr bool operator==(const Iter<C>& i) const {
7094461822SHui Xie return i.it_ == end_;
7194461822SHui Xie }
7294461822SHui Xie
7394461822SHui Xie template <bool C>
operator -(const CrossSizedSent & st,const Iter<C> & it)7494461822SHui Xie friend constexpr auto operator-(const CrossSizedSent& st, const Iter<C>& it) {
7594461822SHui Xie return st.end_ - it.it_;
7694461822SHui Xie }
7794461822SHui Xie
7894461822SHui Xie template <bool C>
operator -(const Iter<C> & it,const CrossSizedSent & st)7994461822SHui Xie friend constexpr auto operator-(const Iter<C>& it, const CrossSizedSent& st) {
8094461822SHui Xie return it.it_ - st.end_;
8194461822SHui Xie }
8294461822SHui Xie };
8394461822SHui Xie
8494461822SHui Xie template <template <bool> class It, template <bool> class St>
8594461822SHui Xie struct Range : TupleBufferView {
8694461822SHui Xie using TupleBufferView::TupleBufferView;
8794461822SHui Xie
8894461822SHui Xie using iterator = It<false>;
8994461822SHui Xie using sentinel = St<false>;
9094461822SHui Xie using const_iterator = It<true>;
9194461822SHui Xie using const_sentinel = St<true>;
9294461822SHui Xie
beginRange9394461822SHui Xie constexpr iterator begin() { return {buffer_}; }
beginRange9494461822SHui Xie constexpr const_iterator begin() const { return {buffer_}; }
endRange9594461822SHui Xie constexpr sentinel end() { return sentinel{buffer_ + size_}; }
endRange9694461822SHui Xie constexpr const_sentinel end() const { return const_sentinel{buffer_ + size_}; }
9794461822SHui Xie };
9894461822SHui Xie
9994461822SHui Xie template <class T, class U>
10094461822SHui Xie concept HasMinus = requires(const T t, const U u) { t - u; };
10194461822SHui Xie
10294461822SHui Xie template <class BaseRange>
10394461822SHui Xie using ElementsView = std::ranges::elements_view<BaseRange, 0>;
10494461822SHui Xie
10594461822SHui Xie template <class BaseRange>
10694461822SHui Xie using ElemIter = std::ranges::iterator_t<ElementsView<BaseRange>>;
10794461822SHui Xie
10894461822SHui Xie template <class BaseRange>
10994461822SHui Xie using EleConstIter = std::ranges::iterator_t<const ElementsView<BaseRange>>;
11094461822SHui Xie
11194461822SHui Xie template <class BaseRange>
11294461822SHui Xie using EleSent = std::ranges::sentinel_t<ElementsView<BaseRange>>;
11394461822SHui Xie
11494461822SHui Xie template <class BaseRange>
11594461822SHui Xie using EleConstSent = std::ranges::sentinel_t<const ElementsView<BaseRange>>;
11694461822SHui Xie
testConstraints()11794461822SHui Xie constexpr void testConstraints() {
11894461822SHui Xie // base is not sized
11994461822SHui Xie {
12094461822SHui Xie using Base = Range<Iter, Sent>;
12194461822SHui Xie static_assert(!HasMinus<EleSent<Base>, ElemIter<Base>>);
12294461822SHui Xie static_assert(!HasMinus<ElemIter<Base>, EleSent<Base>>);
12394461822SHui Xie
12494461822SHui Xie static_assert(!HasMinus<EleSent<Base>, EleConstIter<Base>>);
12594461822SHui Xie static_assert(!HasMinus<EleConstIter<Base>, EleSent<Base>>);
12694461822SHui Xie
12794461822SHui Xie static_assert(!HasMinus<EleConstSent<Base>, EleConstIter<Base>>);
12894461822SHui Xie static_assert(!HasMinus<EleConstIter<Base>, EleConstSent<Base>>);
12994461822SHui Xie
13094461822SHui Xie static_assert(!HasMinus<EleConstSent<Base>, ElemIter<Base>>);
13194461822SHui Xie static_assert(!HasMinus<ElemIter<Base>, EleConstSent<Base>>);
13294461822SHui Xie }
13394461822SHui Xie
13494461822SHui Xie // base is sized but not cross const
13594461822SHui Xie {
13694461822SHui Xie using Base = Range<Iter, SizedSent>;
13794461822SHui Xie static_assert(HasMinus<EleSent<Base>, ElemIter<Base>>);
13894461822SHui Xie static_assert(HasMinus<ElemIter<Base>, EleSent<Base>>);
13994461822SHui Xie
14094461822SHui Xie static_assert(!HasMinus<EleSent<Base>, EleConstIter<Base>>);
14194461822SHui Xie static_assert(!HasMinus<EleConstIter<Base>, EleSent<Base>>);
14294461822SHui Xie
14394461822SHui Xie static_assert(HasMinus<EleConstSent<Base>, EleConstIter<Base>>);
14494461822SHui Xie static_assert(HasMinus<EleConstIter<Base>, EleConstSent<Base>>);
14594461822SHui Xie
14694461822SHui Xie static_assert(!HasMinus<EleConstSent<Base>, ElemIter<Base>>);
14794461822SHui Xie static_assert(!HasMinus<ElemIter<Base>, EleConstSent<Base>>);
14894461822SHui Xie }
14994461822SHui Xie
15094461822SHui Xie // base is cross const sized
15194461822SHui Xie {
15294461822SHui Xie using Base = Range<Iter, CrossSizedSent>;
15394461822SHui Xie static_assert(HasMinus<EleSent<Base>, ElemIter<Base>>);
15494461822SHui Xie static_assert(HasMinus<ElemIter<Base>, EleSent<Base>>);
15594461822SHui Xie
15694461822SHui Xie static_assert(HasMinus<EleSent<Base>, EleConstIter<Base>>);
15794461822SHui Xie static_assert(HasMinus<EleConstIter<Base>, EleSent<Base>>);
15894461822SHui Xie
15994461822SHui Xie static_assert(HasMinus<EleConstSent<Base>, EleConstIter<Base>>);
16094461822SHui Xie static_assert(HasMinus<EleConstIter<Base>, EleConstSent<Base>>);
16194461822SHui Xie
16294461822SHui Xie static_assert(HasMinus<EleConstSent<Base>, ElemIter<Base>>);
16394461822SHui Xie static_assert(HasMinus<ElemIter<Base>, EleConstSent<Base>>);
16494461822SHui Xie }
16594461822SHui Xie }
16694461822SHui Xie
test()16794461822SHui Xie constexpr bool test() {
16894461822SHui Xie std::tuple<int> buffer[] = {{1}, {2}, {3}, {4}, {5}};
16994461822SHui Xie
17094461822SHui Xie // base is sized but not cross const
17194461822SHui Xie {
17294461822SHui Xie using Base = Range<Iter, SizedSent>;
17394461822SHui Xie Base base{buffer};
17494461822SHui Xie auto ev = base | std::views::elements<0>;
17594461822SHui Xie auto iter = ev.begin();
17694461822SHui Xie auto const_iter = std::as_const(ev).begin();
17794461822SHui Xie auto sent = ev.end();
17894461822SHui Xie auto const_sent = std::as_const(ev).end();
17994461822SHui Xie
18094461822SHui Xie assert(iter - sent == -5);
18194461822SHui Xie assert(sent - iter == 5);
18294461822SHui Xie assert(const_iter - const_sent == -5);
18394461822SHui Xie assert(const_sent - const_iter == 5);
18494461822SHui Xie }
18594461822SHui Xie
18694461822SHui Xie // base is cross const sized
18794461822SHui Xie {
18894461822SHui Xie using Base = Range<Iter, CrossSizedSent>;
18994461822SHui Xie Base base{buffer};
19094461822SHui Xie auto ev = base | std::views::elements<0>;
19194461822SHui Xie auto iter = ev.begin();
19294461822SHui Xie auto const_iter = std::as_const(ev).begin();
19394461822SHui Xie auto sent = ev.end();
19494461822SHui Xie auto const_sent = std::as_const(ev).end();
19594461822SHui Xie
19694461822SHui Xie assert(iter - sent == -5);
19794461822SHui Xie assert(sent - iter == 5);
19894461822SHui Xie assert(iter - const_sent == -5);
19994461822SHui Xie assert(const_sent - iter == 5);
20094461822SHui Xie assert(const_iter - sent == -5);
20194461822SHui Xie assert(sent - const_iter == 5);
20294461822SHui Xie assert(const_iter - const_sent == -5);
20394461822SHui Xie assert(const_sent - const_iter == 5);
20494461822SHui Xie }
20594461822SHui Xie
20694461822SHui Xie return true;
20794461822SHui Xie }
20894461822SHui Xie
main(int,char **)20994461822SHui Xie int main(int, char**) {
21094461822SHui Xie test();
21194461822SHui Xie static_assert(test());
21294461822SHui Xie
21394461822SHui Xie return 0;
21494461822SHui Xie }
215