brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.3 KiB · 9b20dac Raw
200 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++17, c++2010 11// template<bool OtherConst>12//   requires sentinel_for<zentinel<Const>, ziperator<OtherConst>>13// friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);14 15#include <cassert>16#include <compare>17#include <ranges>18 19#include "../types.h"20 21using Iterator      = random_access_iterator<int*>;22using ConstIterator = random_access_iterator<const int*>;23 24template <bool Const>25struct ComparableSentinel {26  using Iter = std::conditional_t<Const, ConstIterator, Iterator>;27  Iter iter_;28 29  explicit ComparableSentinel() = default;30  constexpr explicit ComparableSentinel(const Iter& it) : iter_(it) {}31 32  constexpr friend bool operator==(const Iterator& i, const ComparableSentinel& s) { return base(i) == base(s.iter_); }33 34  constexpr friend bool operator==(const ConstIterator& i, const ComparableSentinel& s) {35    return base(i) == base(s.iter_);36  }37};38 39struct ComparableView : IntBufferView {40  using IntBufferView::IntBufferView;41 42  constexpr auto begin() { return Iterator(buffer_); }43  constexpr auto begin() const { return ConstIterator(buffer_); }44  constexpr auto end() { return ComparableSentinel<false>(Iterator(buffer_ + size_)); }45  constexpr auto end() const { return ComparableSentinel<true>(ConstIterator(buffer_ + size_)); }46};47 48struct ConstIncompatibleView : std::ranges::view_base {49  cpp17_input_iterator<int*> begin();50  forward_iterator<const int*> begin() const;51  sentinel_wrapper<cpp17_input_iterator<int*>> end();52  sentinel_wrapper<forward_iterator<const int*>> end() const;53};54 55template <class Iter, class Sent>56concept EqualComparable = std::invocable<std::equal_to<>, const Iter&, const Sent&>;57 58constexpr bool test() {59  int buffer1[4] = {1, 2, 3, 4};60  int buffer2[5] = {1, 2, 3, 4, 5};61  int buffer3[8] = {1, 2, 3, 4, 5, 6, 7, 8};62  {63    // const and non-const have different iterator/sentinel types64    std::ranges::zip_transform_view v{65        MakeTuple{}, NonSimpleNonCommon(buffer1), SimpleNonCommon(buffer2), SimpleNonCommon(buffer3)};66    using ZipTransformView = decltype(v);67    static_assert(!std::ranges::common_range<ZipTransformView>);68    static_assert(!simple_view<ZipTransformView>);69 70    assert(v.begin() != v.end());71    assert(v.begin() + 4 == v.end());72 73    // const_iterator (const int*) converted to iterator (int*)74    assert(v.begin() + 4 == std::as_const(v).end());75 76    using Iter      = std::ranges::iterator_t<decltype(v)>;77    using ConstIter = std::ranges::iterator_t<const decltype(v)>;78    static_assert(!std::is_same_v<Iter, ConstIter>);79    using Sentinel      = std::ranges::sentinel_t<decltype(v)>;80    using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>;81    static_assert(!std::is_same_v<Sentinel, ConstSentinel>);82 83    static_assert(EqualComparable<Iter, Sentinel>);84    static_assert(!EqualComparable<ConstIter, Sentinel>);85    static_assert(EqualComparable<Iter, ConstSentinel>);86    static_assert(EqualComparable<ConstIter, ConstSentinel>);87  }88 89  {90    // underlying const/non-const sentinel can be compared with both const/non-const iterator91    std::ranges::zip_transform_view v{MakeTuple{}, ComparableView(buffer1), ComparableView(buffer2)};92    using ZipTransformView = decltype(v);93    static_assert(!std::ranges::common_range<ZipTransformView>);94    static_assert(!simple_view<ZipTransformView>);95 96    assert(v.begin() != v.end());97    assert(v.begin() + 4 == v.end());98    assert(std::as_const(v).begin() + 4 == v.end());99    assert(std::as_const(v).begin() + 4 == std::as_const(v).end());100    assert(v.begin() + 4 == std::as_const(v).end());101 102    using Iter      = std::ranges::iterator_t<decltype(v)>;103    using ConstIter = std::ranges::iterator_t<const decltype(v)>;104    static_assert(!std::is_same_v<Iter, ConstIter>);105    using Sentinel      = std::ranges::sentinel_t<decltype(v)>;106    using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>;107    static_assert(!std::is_same_v<Sentinel, ConstSentinel>);108 109    static_assert(EqualComparable<Iter, Sentinel>);110    static_assert(EqualComparable<ConstIter, Sentinel>);111    static_assert(EqualComparable<Iter, ConstSentinel>);112    static_assert(EqualComparable<ConstIter, ConstSentinel>);113  }114 115  {116    // underlying const/non-const sentinel cannot be compared with non-const/const iterator117    std::ranges::zip_transform_view v{MakeTuple{}, ComparableView(buffer1), ConstIncompatibleView{}};118    using ZipTransformView = decltype(v);119    static_assert(!std::ranges::common_range<ZipTransformView>);120    static_assert(!simple_view<ZipTransformView>);121 122    using Iter      = std::ranges::iterator_t<decltype(v)>;123    using ConstIter = std::ranges::iterator_t<const decltype(v)>;124    static_assert(!std::is_same_v<Iter, ConstIter>);125    using Sentinel      = std::ranges::sentinel_t<decltype(v)>;126    using ConstSentinel = std::ranges::sentinel_t<const decltype(v)>;127    static_assert(!std::is_same_v<Sentinel, ConstSentinel>);128 129    static_assert(EqualComparable<Iter, Sentinel>);130    static_assert(!EqualComparable<ConstIter, Sentinel>);131    static_assert(!EqualComparable<Iter, ConstSentinel>);132    static_assert(EqualComparable<ConstIter, ConstSentinel>);133  }134 135  {136    // one range137    std::ranges::zip_transform_view v(MakeTuple{}, ComparableView{buffer1});138    assert(v.begin() != v.end());139    assert(v.begin() + 4 == v.end());140    assert(v.begin() + 4 == std::as_const(v).end());141  }142 143  {144    // two ranges145    std::ranges::zip_transform_view v(GetFirst{}, ComparableView{buffer2}, std::views::iota(0));146    assert(v.begin() != v.end());147    assert(v.begin() + 5 == v.end());148    assert(v.begin() + 5 == std::as_const(v).end());149  }150 151  {152    // three ranges153    std::ranges::zip_transform_view v(154        Tie{}, ComparableView{buffer1}, SimpleNonCommon{buffer2}, std::ranges::single_view(2.));155    assert(v.begin() != v.end());156    assert(v.begin() + 1 == v.end());157    assert(v.begin() + 1 == std::as_const(v).end());158  }159 160  {161    // single empty range162    std::ranges::zip_transform_view v(MakeTuple{}, ComparableView(nullptr, 0));163    assert(v.begin() == v.end());164    assert(std::as_const(v).begin() == std::as_const(v).end());165  }166 167  {168    // empty range at the beginning169    std::ranges::zip_transform_view v(170        MakeTuple{}, std::ranges::empty_view<int>(), ComparableView{buffer1}, SimpleCommon{buffer2});171    assert(v.begin() == v.end());172    assert(std::as_const(v).begin() == std::as_const(v).end());173  }174 175  {176    // empty range in the middle177    std::ranges::zip_transform_view v(178        MakeTuple{}, SimpleCommon{buffer1}, std::ranges::empty_view<int>(), ComparableView{buffer2});179    assert(v.begin() == v.end());180    assert(std::as_const(v).begin() == std::as_const(v).end());181  }182 183  {184    // empty range at the end185    std::ranges::zip_transform_view v(186        MakeTuple{}, SimpleCommon{buffer1}, ComparableView{buffer2}, std::ranges::empty_view<int>());187    assert(v.begin() == v.end());188    assert(std::as_const(v).begin() == std::as_const(v).end());189  }190 191  return true;192}193 194int main(int, char**) {195  test();196  static_assert(test());197 198  return 0;199}200