File: iterator_sentinel.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 (147 lines) | stat: -rw-r--r-- 5,458 bytes parent folder | download | duplicates (8)
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
//===---------------------------------------------------------------------===//
//
// 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

// <span>

// template <class It, class End>
// constexpr explicit(Extent != dynamic_extent) span(It first, End last);
// Requires: [first, last) shall be a valid range.
//   If Extent is not equal to dynamic_extent, then last - first shall be equal to Extent.
// Throws: When and what last - first throws.

#include <array>
#include <span>
#include <cassert>
#include <utility>

#include "assert_macros.h"
#include "test_iterators.h"
#include "test_macros.h"

template <class T, class Sentinel>
constexpr bool test_ctor() {
  T val[2] = {};
  auto s1  = std::span<T>(std::begin(val), Sentinel(std::end(val)));
  auto s2  = std::span<T, 2>(std::begin(val), Sentinel(std::end(val)));
  assert(s1.data() == std::data(val) && s1.size() == std::size(val));
  assert(s2.data() == std::data(val) && s2.size() == std::size(val));
  return true;
}

template <std::size_t Extent>
constexpr void test_constructibility() {
  static_assert(std::is_constructible_v<std::span<int, Extent>, int*, int*>);
  static_assert(!std::is_constructible_v<std::span<int, Extent>, const int*, const int*>);
  static_assert(!std::is_constructible_v<std::span<int, Extent>, volatile int*, volatile int*>);
  static_assert(std::is_constructible_v<std::span<const int, Extent>, int*, int*>);
  static_assert(std::is_constructible_v<std::span<const int, Extent>, const int*, const int*>);
  static_assert(!std::is_constructible_v<std::span<const int, Extent>, volatile int*, volatile int*>);
  static_assert(std::is_constructible_v<std::span<volatile int, Extent>, int*, int*>);
  static_assert(!std::is_constructible_v<std::span<volatile int, Extent>, const int*, const int*>);
  static_assert(std::is_constructible_v<std::span<volatile int, Extent>, volatile int*, volatile int*>);
  static_assert(!std::is_constructible_v<std::span<int, Extent>, int*, float*>); // types wrong
}

constexpr bool test() {
  test_constructibility<std::dynamic_extent>();
  test_constructibility<3>();
  struct A {};
  assert((test_ctor<int, int*>()));
  assert((test_ctor<int, sized_sentinel<int*>>()));
  assert((test_ctor<A, A*>()));
  assert((test_ctor<A, sized_sentinel<A*>>()));
  return true;
}

#ifndef TEST_HAS_NO_EXCEPTIONS
// A stripped down contiguous iterator that throws when using operator-.
template <class It>
class throw_operator_minus {
  It it_;

public:
  typedef std::contiguous_iterator_tag iterator_category;
  typedef typename std::iterator_traits<It>::value_type value_type;
  typedef typename std::iterator_traits<It>::difference_type difference_type;
  typedef It pointer;
  typedef typename std::iterator_traits<It>::reference reference;
  typedef std::remove_reference_t<reference> element_type;

  throw_operator_minus() : it_() {}
  explicit throw_operator_minus(It it) : it_(it) {}

  reference operator*() const { return *it_; }
  pointer operator->() const { return it_; }
  reference operator[](difference_type n) const { return it_[n]; }

  throw_operator_minus& operator++() {
    ++it_;
    return *this;
  }
  throw_operator_minus& operator--() {
    --it_;
    return *this;
  }
  throw_operator_minus operator++(int) { return throw_operator_minus(it_++); }
  throw_operator_minus operator--(int) { return throw_operator_minus(it_--); }

  throw_operator_minus& operator+=(difference_type n) {
    it_ += n;
    return *this;
  }
  throw_operator_minus& operator-=(difference_type n) {
    it_ -= n;
    return *this;
  }
  friend throw_operator_minus operator+(throw_operator_minus x, difference_type n) {
    x += n;
    return x;
  }
  friend throw_operator_minus operator+(difference_type n, throw_operator_minus x) {
    x += n;
    return x;
  }
  friend throw_operator_minus operator-(throw_operator_minus x, difference_type n) {
    x -= n;
    return x;
  }
  friend difference_type operator-(throw_operator_minus, throw_operator_minus) { throw 42; };

  friend bool operator==(const throw_operator_minus& x, const throw_operator_minus& y) { return x.it_ == y.it_; }
  friend bool operator<(const throw_operator_minus& x, const throw_operator_minus& y) { return x.it_ < y.it_; }
  friend bool operator>(const throw_operator_minus& x, const throw_operator_minus& y) { return x.it_ > y.it_; }
  friend bool operator<=(const throw_operator_minus& x, const throw_operator_minus& y) { return x.it_ <= y.it_; }
  friend bool operator>=(const throw_operator_minus& x, const throw_operator_minus& y) { return x.it_ >= y.it_; }
};

template <class It>
throw_operator_minus(It) -> throw_operator_minus<It>;

void test_exceptions() {
  std::array a{42};
  TEST_VALIDATE_EXCEPTION(
      int,
      [](int i) { assert(i == 42); },
      (std::span<int>{throw_operator_minus{a.begin()}, throw_operator_minus{a.end()}}));
  TEST_VALIDATE_EXCEPTION(
      int,
      [](int i) { assert(i == 42); },
      (std::span<int, 1>{throw_operator_minus{a.begin()}, throw_operator_minus{a.end()}}));
}
#endif // TEST_HAS_NO_EXCEPTIONS

int main(int, char**) {
  test();
#ifndef TEST_HAS_NO_EXCEPTIONS
  test_exceptions();
#endif
  static_assert(test());

  return 0;
}