xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/minus.pass.cpp (revision 3fe3f9c51cbac91af741e53e96c89f633bd2a6ad)
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