File: eq.pass.cpp

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 1,998,492 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (143 lines) | stat: -rw-r--r-- 5,974 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03, c++11, c++14, c++17

// friend constexpr bool operator==(const CI<Const>& y, const sentinel& x);
// template<bool OtherConst = !Const>
//   requires sentinel_for<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
// friend constexpr bool operator==(const CI<OtherConst>& y, const sentinel& x);

#include <cassert>
#include <cstddef>
#include <ranges>
#include <type_traits>
#include <utility>

#include "test_comparisons.h"
#include "test_iterators.h"
#include "test_range.h"

template <bool Const>
using MaybeConstIterator = cpp20_input_iterator<std::conditional_t<Const, const int*, int*>>;

template <bool Const>
class CrossConstComparableSentinel {
  using Base = std::conditional_t<Const, const int*, int*>;
  Base base_;

public:
  CrossConstComparableSentinel() = default;
  constexpr explicit CrossConstComparableSentinel(Base base) : base_(base) {}

  friend constexpr bool operator==(const MaybeConstIterator<Const>& it, const CrossConstComparableSentinel& se) {
    return base(it) == se.base_;
  }

  friend constexpr bool operator==(const MaybeConstIterator<!Const>& it, const CrossConstComparableSentinel& se) {
    return base(it) == se.base_;
  }
};

static_assert(std::sentinel_for<CrossConstComparableSentinel<true>, MaybeConstIterator<false>>);
static_assert(std::sentinel_for<CrossConstComparableSentinel<true>, MaybeConstIterator<true>>);
static_assert(std::sentinel_for<CrossConstComparableSentinel<false>, MaybeConstIterator<false>>);
static_assert(std::sentinel_for<CrossConstComparableSentinel<false>, MaybeConstIterator<true>>);

struct CrossConstComparableView : std::ranges::view_base {
  template <std::size_t N>
  constexpr explicit CrossConstComparableView(int (&arr)[N]) : b_(arr), e_(arr + N) {}

  constexpr MaybeConstIterator<false> begin() { return MaybeConstIterator<false>{b_}; }
  constexpr CrossConstComparableSentinel<false> end() { return CrossConstComparableSentinel<false>{e_}; }

  constexpr MaybeConstIterator<true> begin() const { return MaybeConstIterator<true>{b_}; }
  constexpr CrossConstComparableSentinel<true> end() const { return CrossConstComparableSentinel<true>{e_}; }

private:
  int* b_;
  int* e_;
};

static_assert(std::ranges::range<CrossConstComparableView>);
static_assert(std::ranges::range<const CrossConstComparableView>);

struct NonCrossConstComparableView : std::ranges::view_base {
  int* begin();
  sentinel_wrapper<int*> end();

  long* begin() const;
  sentinel_wrapper<long*> end() const;
};

static_assert(std::ranges::range<NonCrossConstComparableView>);
static_assert(std::ranges::range<const NonCrossConstComparableView>);

constexpr bool test() {
  int buffer[8]                      = {1, 2, 3, 4, 5, 6, 7, 8};
  using CrossConstComparableTakeView = std::ranges::take_view<CrossConstComparableView>;

  {   // Compare CI<Const> with sentinel<Const>
    { // Const == true
      AssertEqualityReturnBool<std::ranges::iterator_t<const CrossConstComparableTakeView>,
                               std::ranges::sentinel_t<const CrossConstComparableTakeView>>();
      const CrossConstComparableTakeView tv(CrossConstComparableView{buffer}, 4);
      assert(testEquality(std::ranges::next(tv.begin(), 4), tv.end(), true));
      assert(testEquality(tv.begin(), tv.end(), false));
    }

    { // Const == false
      AssertEqualityReturnBool<std::ranges::iterator_t<CrossConstComparableTakeView>,
                               std::ranges::sentinel_t<CrossConstComparableTakeView>>();
      CrossConstComparableTakeView tv(CrossConstComparableView{buffer}, 4);
      assert(testEquality(std::ranges::next(tv.begin(), 4), tv.end(), true));
      assert(testEquality(std::ranges::next(tv.begin(), 1), tv.end(), false));
    }
  }

  {   // Compare CI<Const> with sentinel<!Const>
    { // Const == true
      AssertEqualityReturnBool<std::ranges::iterator_t<const CrossConstComparableTakeView>,
                               std::ranges::sentinel_t<CrossConstComparableTakeView>>();
      CrossConstComparableTakeView tv(CrossConstComparableView{buffer}, 4);
      assert(testEquality(std::ranges::next(std::as_const(tv).begin(), 4), tv.end(), true));
      assert(testEquality(std::ranges::next(std::as_const(tv).begin(), 2), tv.end(), false));
    }

    { // Const == false
      AssertEqualityReturnBool<std::ranges::iterator_t<CrossConstComparableTakeView>,
                               std::ranges::sentinel_t<const CrossConstComparableTakeView>>();
      CrossConstComparableTakeView tv(CrossConstComparableView{buffer}, 4);
      assert(testEquality(std::ranges::next(tv.begin(), 4), std::as_const(tv).end(), true));
      assert(testEquality(std::ranges::next(tv.begin(), 3), std::as_const(tv).end(), false));
    }
  }

  { // Check invalid comparisons between CI<Const> and sentinel<!Const>
    using TakeView = std::ranges::take_view<NonCrossConstComparableView>;
    static_assert(
        !weakly_equality_comparable_with<std::ranges::iterator_t<const TakeView>, std::ranges::sentinel_t<TakeView>>);
    static_assert(
        !weakly_equality_comparable_with<std::ranges::iterator_t<TakeView>, std::ranges::sentinel_t<const TakeView>>);

    // Those should be valid
    static_assert(
        weakly_equality_comparable_with<std::ranges::iterator_t<TakeView>, std::ranges::sentinel_t<TakeView>>);
    static_assert(weakly_equality_comparable_with<std::ranges::iterator_t<const TakeView>,
                                                  std::ranges::sentinel_t<const TakeView>>);
  }

  return true;
}

int main(int, char**) {
  test();
  static_assert(test());

  return 0;
}