File: begin.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 (161 lines) | stat: -rw-r--r-- 6,060 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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//===----------------------------------------------------------------------===//
//
// 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

// constexpr auto begin()
//   requires (!(simple-view<V> &&
//               random_access_range<const V> && sized_range<const V>));
// constexpr auto begin() const
//   requires random_access_range<const V> && sized_range<const V>;

#include <ranges>

#include "test_macros.h"
#include "test_iterators.h"
#include "test_range.h"
#include "types.h"

template<class T>
concept BeginInvocable = requires(std::ranges::drop_view<T> t) { t.begin(); };

template <bool IsSimple>
struct MaybeSimpleView : std::ranges::view_base {
  int* num_of_non_const_begin_calls;
  int* num_of_const_begin_calls;

  constexpr int* begin() {
    ++(*num_of_non_const_begin_calls);
    return nullptr;
  }
  constexpr std::conditional_t<IsSimple, int*, const int*> begin() const {
    ++(*num_of_const_begin_calls);
    return nullptr;
  }
  constexpr int* end() const { return nullptr; }
  constexpr std::size_t size() const { return 0; }
};

using SimpleView = MaybeSimpleView<true>;
using NonSimpleView = MaybeSimpleView<false>;

constexpr bool test() {
  // random_access_range<const V> && sized_range<const V>
  std::ranges::drop_view dropView1(MoveOnlyView(), 4);
  assert(dropView1.begin() == globalBuff + 4);

  // !random_access_range<const V>
  std::ranges::drop_view dropView2(ForwardView(), 4);
  assert(base(dropView2.begin()) == globalBuff + 4);

  // !random_access_range<const V>
  std::ranges::drop_view dropView3(InputView(), 4);
  assert(base(dropView3.begin()) == globalBuff + 4);

  // random_access_range<const V> && sized_range<const V>
  std::ranges::drop_view dropView4(MoveOnlyView(), 8);
  assert(dropView4.begin() == globalBuff + 8);

  // random_access_range<const V> && sized_range<const V>
  std::ranges::drop_view dropView5(MoveOnlyView(), 0);
  assert(dropView5.begin() == globalBuff);

  // random_access_range<const V> && sized_range<const V>
  const std::ranges::drop_view dropView6(MoveOnlyView(), 0);
  assert(dropView6.begin() == globalBuff);

  // random_access_range<const V> && sized_range<const V>
  std::ranges::drop_view dropView7(MoveOnlyView(), 10);
  assert(dropView7.begin() == globalBuff + 8);

  IteratorOpCounts opcounts;
  CountedView view8(&opcounts);
  ;
  std::ranges::drop_view dropView8(view8, 5);
  assert(base(base(dropView8.begin())) == globalBuff + 5);
  assert(opcounts.increments == 5);

  static_assert(!BeginInvocable<const ForwardView>);

  {
    // non-common non-simple view,
    // The wording of the standard is:
    // Returns: ranges::next(ranges::begin(base_), count_, ranges::end(base_))
    // Note that "Returns" is used here, meaning that we don't have to do it this way.
    // In fact, this will use ranges::advance that has O(n) on non-common range.
    // but [range.range] requires "amortized constant time" for ranges::begin and ranges::end
    // Here, we test that begin() is indeed constant time, by creating a customized
    // sentinel and counting how many times the sentinel eq function is called.
    // It should be 0 times, but since this test (or any test under libcxx/test/std) is
    // also used by other implementations, we relax the condition to that
    // sentinel_cmp_calls is a constant number.
    int sentinel_cmp_calls_1 = 0;
    int sentinel_cmp_calls_2 = 0;
    using NonCommonView      = MaybeSimpleNonCommonView<false>;
    static_assert(std::ranges::random_access_range<NonCommonView>);
    static_assert(std::ranges::sized_range<NonCommonView>);
    std::ranges::drop_view dropView9_1(NonCommonView{{}, 0, &sentinel_cmp_calls_1}, 4);
    std::ranges::drop_view dropView9_2(NonCommonView{{}, 0, &sentinel_cmp_calls_2}, 6);
    assert(dropView9_1.begin() == globalBuff + 4);
    assert(dropView9_2.begin() == globalBuff + 6);
    assert(sentinel_cmp_calls_1 == sentinel_cmp_calls_2);
  }

  {
    // non-common simple view, same as above.
    int sentinel_cmp_calls_1 = 0;
    int sentinel_cmp_calls_2 = 0;
    using NonCommonView      = MaybeSimpleNonCommonView<true>;
    static_assert(std::ranges::random_access_range<NonCommonView>);
    static_assert(std::ranges::sized_range<NonCommonView>);
    std::ranges::drop_view dropView10_1(NonCommonView{{}, 0, &sentinel_cmp_calls_1}, 4);
    std::ranges::drop_view dropView10_2(NonCommonView{{}, 0, &sentinel_cmp_calls_2}, 6);
    assert(dropView10_1.begin() == globalBuff + 4);
    assert(dropView10_2.begin() == globalBuff + 6);
    assert(sentinel_cmp_calls_1 == sentinel_cmp_calls_2);
  }

  {
    static_assert(std::ranges::random_access_range<const SimpleView>);
    static_assert(std::ranges::sized_range<const SimpleView>);
    static_assert(simple_view<SimpleView>);
    int non_const_calls = 0;
    int const_calls = 0;
    std::ranges::drop_view dropView(SimpleView{{}, &non_const_calls, &const_calls}, 4);
    assert(dropView.begin() == nullptr);
    assert(non_const_calls == 0);
    assert(const_calls == 1);
    assert(std::as_const(dropView).begin() == nullptr);
    assert(non_const_calls == 0);
    assert(const_calls == 2);
  }

  {
    static_assert(std::ranges::random_access_range<const NonSimpleView>);
    static_assert(std::ranges::sized_range<const NonSimpleView>);
    static_assert(!simple_view<NonSimpleView>);
    int non_const_calls = 0;
    int const_calls = 0;
    std::ranges::drop_view dropView(NonSimpleView{{}, &non_const_calls, &const_calls}, 4);
    assert(dropView.begin() == nullptr);
    assert(non_const_calls == 1);
    assert(const_calls == 0);
    assert(std::as_const(dropView).begin() == nullptr);
    assert(non_const_calls == 1);
    assert(const_calls == 1);
  }

  return true;
}

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

  return 0;
}