xref: /llvm-project/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp (revision a72ab9c14d604ae857acad5ed7d6b5be6914c619)
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