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