brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.5 KiB · 343bf80 Raw
215 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// template<bool OtherConst>12//   requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>13// friend constexpr range_difference_t<maybe-const<OtherConst, V>>14//   operator-(const iterator<OtherConst>& x, const sentinel& y);15//16// template<bool OtherConst>17//   requires sized_sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>18// friend constexpr range_difference_t<maybe-const<OtherConst, V>>19//   operator-(const sentinel& x, const iterator<OtherConst>& y);20 21#include <cassert>22#include <concepts>23#include <cstddef>24#include <functional>25#include <ranges>26#include <tuple>27 28#include "../types.h"29 30template <bool Const>31struct Iter {32  std::tuple<int>* it_;33 34  using value_type       = std::tuple<int>;35  using difference_type  = std::ptrdiff_t;36  using iterator_concept = std::input_iterator_tag;37 38  constexpr decltype(auto) operator*() const { return *it_; }39  constexpr Iter& operator++() {40    ++it_;41    return *this;42  }43  constexpr void operator++(int) { ++it_; }44};45 46template <bool Const>47struct Sent {48  std::tuple<int>* end_;49 50  constexpr bool operator==(const Iter<Const>& i) const { return i.it_ == end_; }51};52 53template <bool Const>54struct SizedSent {55  std::tuple<int>* end_;56 57  constexpr bool operator==(const Iter<Const>& i) const { return i.it_ == end_; }58 59  friend constexpr auto operator-(const SizedSent& st, const Iter<Const>& it) { return st.end_ - it.it_; }60 61  friend constexpr auto operator-(const Iter<Const>& it, const SizedSent& st) { return it.it_ - st.end_; }62};63 64template <bool Const>65struct CrossSizedSent {66  std::tuple<int>* end_;67 68  template <bool C>69  constexpr bool operator==(const Iter<C>& i) const {70    return i.it_ == end_;71  }72 73  template <bool C>74  friend constexpr auto operator-(const CrossSizedSent& st, const Iter<C>& it) {75    return st.end_ - it.it_;76  }77 78  template <bool C>79  friend constexpr auto operator-(const Iter<C>& it, const CrossSizedSent& st) {80    return it.it_ - st.end_;81  }82};83 84template <template <bool> class It, template <bool> class St>85struct Range : TupleBufferView {86  using TupleBufferView::TupleBufferView;87 88  using iterator       = It<false>;89  using sentinel       = St<false>;90  using const_iterator = It<true>;91  using const_sentinel = St<true>;92 93  constexpr iterator begin() { return {buffer_}; }94  constexpr const_iterator begin() const { return {buffer_}; }95  constexpr sentinel end() { return sentinel{buffer_ + size_}; }96  constexpr const_sentinel end() const { return const_sentinel{buffer_ + size_}; }97};98 99template <class T, class U>100concept HasMinus = requires(const T t, const U u) { t - u; };101 102template <class BaseRange>103using ElementsView = std::ranges::elements_view<BaseRange, 0>;104 105template <class BaseRange>106using ElemIter = std::ranges::iterator_t<ElementsView<BaseRange>>;107 108template <class BaseRange>109using EleConstIter = std::ranges::iterator_t<const ElementsView<BaseRange>>;110 111template <class BaseRange>112using EleSent = std::ranges::sentinel_t<ElementsView<BaseRange>>;113 114template <class BaseRange>115using EleConstSent = std::ranges::sentinel_t<const ElementsView<BaseRange>>;116 117constexpr void testConstraints() {118  // base is not sized119  {120    using Base = Range<Iter, Sent>;121    static_assert(!HasMinus<EleSent<Base>, ElemIter<Base>>);122    static_assert(!HasMinus<ElemIter<Base>, EleSent<Base>>);123 124    static_assert(!HasMinus<EleSent<Base>, EleConstIter<Base>>);125    static_assert(!HasMinus<EleConstIter<Base>, EleSent<Base>>);126 127    static_assert(!HasMinus<EleConstSent<Base>, EleConstIter<Base>>);128    static_assert(!HasMinus<EleConstIter<Base>, EleConstSent<Base>>);129 130    static_assert(!HasMinus<EleConstSent<Base>, ElemIter<Base>>);131    static_assert(!HasMinus<ElemIter<Base>, EleConstSent<Base>>);132  }133 134  // base is sized but not cross const135  {136    using Base = Range<Iter, SizedSent>;137    static_assert(HasMinus<EleSent<Base>, ElemIter<Base>>);138    static_assert(HasMinus<ElemIter<Base>, EleSent<Base>>);139 140    static_assert(!HasMinus<EleSent<Base>, EleConstIter<Base>>);141    static_assert(!HasMinus<EleConstIter<Base>, EleSent<Base>>);142 143    static_assert(HasMinus<EleConstSent<Base>, EleConstIter<Base>>);144    static_assert(HasMinus<EleConstIter<Base>, EleConstSent<Base>>);145 146    static_assert(!HasMinus<EleConstSent<Base>, ElemIter<Base>>);147    static_assert(!HasMinus<ElemIter<Base>, EleConstSent<Base>>);148  }149 150  // base is cross const sized151  {152    using Base = Range<Iter, CrossSizedSent>;153    static_assert(HasMinus<EleSent<Base>, ElemIter<Base>>);154    static_assert(HasMinus<ElemIter<Base>, EleSent<Base>>);155 156    static_assert(HasMinus<EleSent<Base>, EleConstIter<Base>>);157    static_assert(HasMinus<EleConstIter<Base>, EleSent<Base>>);158 159    static_assert(HasMinus<EleConstSent<Base>, EleConstIter<Base>>);160    static_assert(HasMinus<EleConstIter<Base>, EleConstSent<Base>>);161 162    static_assert(HasMinus<EleConstSent<Base>, ElemIter<Base>>);163    static_assert(HasMinus<ElemIter<Base>, EleConstSent<Base>>);164  }165}166 167constexpr bool test() {168  std::tuple<int> buffer[] = {{1}, {2}, {3}, {4}, {5}};169 170  // base is sized but not cross const171  {172    using Base = Range<Iter, SizedSent>;173    Base base{buffer};174    auto ev         = base | std::views::elements<0>;175    auto iter       = ev.begin();176    auto const_iter = std::as_const(ev).begin();177    auto sent       = ev.end();178    auto const_sent = std::as_const(ev).end();179 180    assert(iter - sent == -5);181    assert(sent - iter == 5);182    assert(const_iter - const_sent == -5);183    assert(const_sent - const_iter == 5);184  }185 186  // base is cross const sized187  {188    using Base = Range<Iter, CrossSizedSent>;189    Base base{buffer};190    auto ev         = base | std::views::elements<0>;191    auto iter       = ev.begin();192    auto const_iter = std::as_const(ev).begin();193    auto sent       = ev.end();194    auto const_sent = std::as_const(ev).end();195 196    assert(iter - sent == -5);197    assert(sent - iter == 5);198    assert(iter - const_sent == -5);199    assert(const_sent - iter == 5);200    assert(const_iter - sent == -5);201    assert(sent - const_iter == 5);202    assert(const_iter - const_sent == -5);203    assert(const_sent - const_iter == 5);204  }205 206  return true;207}208 209int main(int, char**) {210  test();211  static_assert(test());212 213  return 0;214}215