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-exception
6//
7//===----------------------------------------------------------------------===//
8
9// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
10
11// <span>
12
13// constexpr reference at(size_type idx) const; // since C++26
14
15#include <array>
16#include <cassert>
17#include <concepts>
18#include <limits>
19#include <span>
20#include <stdexcept>
21#include <string>
22#include <tuple>
23#include <utility>
24#include <vector>
25
26#include "test_macros.h"
27
28template <typename ReferenceT>
29constexpr void testSpanAt(auto&& anySpan, int index, int expectedValue) {
30 // non-const
31 {
32 std::same_as<ReferenceT> decltype(auto) elem = anySpan.at(index);
33 assert(elem == expectedValue);
34 }
35
36 // const
37 {
38 std::same_as<ReferenceT> decltype(auto) elem = std::as_const(anySpan).at(index);
39 assert(elem == expectedValue);
40 }
41}
42
43constexpr bool test() {
44 // With static extent
45 {
46 std::array arr{0, 1, 2, 3, 4, 5, 9084};
47 std::span arrSpan{arr};
48
49 assert(std::dynamic_extent != arrSpan.extent);
50
51 using ReferenceT = typename decltype(arrSpan)::reference;
52
53 testSpanAt<ReferenceT>(arrSpan, 0, 0);
54 testSpanAt<ReferenceT>(arrSpan, 1, 1);
55 testSpanAt<ReferenceT>(arrSpan, 6, 9084);
56 }
57
58 // With dynamic extent
59 {
60 std::vector vec{0, 1, 2, 3, 4, 5, 9084};
61 std::span vecSpan{vec};
62
63 assert(std::dynamic_extent == vecSpan.extent);
64
65 using ReferenceT = typename decltype(vecSpan)::reference;
66
67 testSpanAt<ReferenceT>(vecSpan, 0, 0);
68 testSpanAt<ReferenceT>(vecSpan, 1, 1);
69 testSpanAt<ReferenceT>(vecSpan, 6, 9084);
70 }
71
72 return true;
73}
74
75void test_exceptions() {
76#ifndef TEST_HAS_NO_EXCEPTIONS
77 using namespace std::string_literals;
78
79 // With static extent
80 {
81 std::array arr{0, 1, 2, 3, 4, 5, 9084, std::numeric_limits<int>::max()};
82 const std::span arrSpan{arr};
83
84 try {
85 using SizeT = typename decltype(arrSpan)::size_type;
86 std::ignore = arrSpan.at(std::numeric_limits<SizeT>::max());
87 assert(false);
88 } catch ([[maybe_unused]] const std::out_of_range& e) {
89 // pass
90 LIBCPP_ASSERT(e.what() == "span"s);
91 } catch (...) {
92 assert(false);
93 }
94
95 try {
96 std::ignore = arrSpan.at(arr.size());
97 assert(false);
98 } catch ([[maybe_unused]] const std::out_of_range& e) {
99 // pass
100 LIBCPP_ASSERT(e.what() == "span"s);
101 } catch (...) {
102 assert(false);
103 }
104
105 try {
106 std::ignore = arrSpan.at(arr.size() - 1);
107 // pass
108 assert(arrSpan.at(arr.size() - 1) == std::numeric_limits<int>::max());
109 } catch (...) {
110 assert(false);
111 }
112 }
113
114 {
115 std::array<int, 0> arr{};
116 const std::span arrSpan{arr};
117
118 try {
119 std::ignore = arrSpan.at(0);
120 assert(false);
121 } catch ([[maybe_unused]] const std::out_of_range& e) {
122 // pass
123 LIBCPP_ASSERT(e.what() == "span"s);
124 } catch (...) {
125 assert(false);
126 }
127 }
128
129 // With dynamic extent
130
131 {
132 std::vector vec{0, 1, 2, 3, 4, 5, 9084, std::numeric_limits<int>::max()};
133 const std::span vecSpan{vec};
134
135 try {
136 using SizeT = typename decltype(vecSpan)::size_type;
137 std::ignore = vecSpan.at(std::numeric_limits<SizeT>::max());
138 assert(false);
139 } catch ([[maybe_unused]] const std::out_of_range& e) {
140 // pass
141 LIBCPP_ASSERT(e.what() == "span"s);
142 } catch (...) {
143 assert(false);
144 }
145
146 try {
147 std::ignore = vecSpan.at(vec.size());
148 assert(false);
149 } catch (const std::out_of_range& e) {
150 // pass
151 LIBCPP_ASSERT(e.what() == "span"s);
152 } catch (...) {
153 assert(false);
154 }
155
156 try {
157 std::ignore = vecSpan.at(vec.size() - 1);
158 assert(vecSpan.at(vec.size() - 1) == std::numeric_limits<int>::max());
159 } catch (...) {
160 assert(false);
161 }
162 }
163
164 {
165 std::vector<int> vec{};
166 const std::span vecSpan{vec};
167
168 try {
169 std::ignore = vecSpan.at(0);
170 assert(false);
171 } catch ([[maybe_unused]] const std::out_of_range& e) {
172 // pass
173 LIBCPP_ASSERT(e.what() == "span"s);
174 } catch (...) {
175 assert(false);
176 }
177 }
178#endif // TEST_HAS_NO_EXCEPTIONS
179}
180
181int main(int, char**) {
182 test();
183 static_assert(test());
184
185 test_exceptions();
186
187 return 0;
188}
189

source code of libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp