189 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++2310 11// <span>12 13// constexpr reference at(size_type idx) const; // since C++2614 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-const31 {32 std::same_as<ReferenceT> decltype(auto) elem = anySpan.at(index);33 assert(elem == expectedValue);34 }35 36 // const37 {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 extent45 {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 extent59 {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_EXCEPTIONS77 using namespace std::string_literals;78 79 // With static extent80 {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 // pass90 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 // pass100 LIBCPP_ASSERT(e.what() == "span"s);101 } catch (...) {102 assert(false);103 }104 105 try {106 std::ignore = arrSpan.at(arr.size() - 1);107 // pass108 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 // pass123 LIBCPP_ASSERT(e.what() == "span"s);124 } catch (...) {125 assert(false);126 }127 }128 129 // With dynamic extent130 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 // pass141 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 // pass151 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 // pass173 LIBCPP_ASSERT(e.what() == "span"s);174 } catch (...) {175 assert(false);176 }177 }178#endif // TEST_HAS_NO_EXCEPTIONS179}180 181int main(int, char**) {182 test();183 static_assert(test());184 185 test_exceptions();186 187 return 0;188}189