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 // UNSUPPORTED: c++03, c++11, c++14, c++17 9 10 // <span> 11 12 // template<size_t Offset, size_t Count = dynamic_extent> 13 // constexpr span<element_type, see below> subspan() const; 14 // 15 // constexpr span<element_type, dynamic_extent> subspan( 16 // size_type offset, size_type count = dynamic_extent) const; 17 // 18 // Requires: (0 <= Offset && Offset <= size()) 19 // && (Count == dynamic_extent || Count >= 0 && Offset + Count <= size()) 20 21 #include <span> 22 #include <cassert> 23 #include <algorithm> 24 #include <string> 25 26 #include "test_macros.h" 27 28 template <typename Span, size_t Offset, size_t Count> 29 constexpr bool testConstexprSpan(Span sp) 30 { 31 LIBCPP_ASSERT((noexcept(sp.template subspan<Offset, Count>()))); 32 LIBCPP_ASSERT((noexcept(sp.subspan(Offset, Count)))); 33 auto s1 = sp.template subspan<Offset, Count>(); 34 auto s2 = sp.subspan(Offset, Count); 35 using S1 = decltype(s1); 36 using S2 = decltype(s2); 37 ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); 38 ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); 39 static_assert(S1::extent == Count); 40 static_assert(S2::extent == std::dynamic_extent, ""); 41 return 42 s1.data() == s2.data() 43 && s1.size() == s2.size() 44 && std::equal(s1.begin(), s1.end(), sp.begin() + Offset); 45 } 46 47 template <typename Span, size_t Offset> 48 constexpr bool testConstexprSpan(Span sp) 49 { 50 LIBCPP_ASSERT((noexcept(sp.template subspan<Offset>()))); 51 LIBCPP_ASSERT((noexcept(sp.subspan(Offset)))); 52 auto s1 = sp.template subspan<Offset>(); 53 auto s2 = sp.subspan(Offset); 54 using S1 = decltype(s1); 55 using S2 = decltype(s2); 56 ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); 57 ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); 58 static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Span::extent - Offset), ""); 59 static_assert(S2::extent == std::dynamic_extent, ""); 60 return 61 s1.data() == s2.data() 62 && s1.size() == s2.size() 63 && std::equal(s1.begin(), s1.end(), sp.begin() + Offset, sp.end()); 64 } 65 66 67 template <typename Span, size_t Offset, size_t Count> 68 void testRuntimeSpan(Span sp) 69 { 70 LIBCPP_ASSERT((noexcept(sp.template subspan<Offset, Count>()))); 71 LIBCPP_ASSERT((noexcept(sp.subspan(Offset, Count)))); 72 auto s1 = sp.template subspan<Offset, Count>(); 73 auto s2 = sp.subspan(Offset, Count); 74 using S1 = decltype(s1); 75 using S2 = decltype(s2); 76 ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); 77 ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); 78 static_assert(S1::extent == Count); 79 static_assert(S2::extent == std::dynamic_extent, ""); 80 assert(s1.data() == s2.data()); 81 assert(s1.size() == s2.size()); 82 assert(std::equal(s1.begin(), s1.end(), sp.begin() + Offset)); 83 } 84 85 86 template <typename Span, size_t Offset> 87 void testRuntimeSpan(Span sp) 88 { 89 LIBCPP_ASSERT((noexcept(sp.template subspan<Offset>()))); 90 LIBCPP_ASSERT((noexcept(sp.subspan(Offset)))); 91 auto s1 = sp.template subspan<Offset>(); 92 auto s2 = sp.subspan(Offset); 93 using S1 = decltype(s1); 94 using S2 = decltype(s2); 95 ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); 96 ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); 97 static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Span::extent - Offset), ""); 98 static_assert(S2::extent == std::dynamic_extent, ""); 99 assert(s1.data() == s2.data()); 100 assert(s1.size() == s2.size()); 101 assert(std::equal(s1.begin(), s1.end(), sp.begin() + Offset, sp.end())); 102 } 103 104 105 constexpr int carr1[] = {1,2,3,4}; 106 int arr1[] = {5,6,7}; 107 108 int main(int, char**) 109 { 110 { 111 using Sp = std::span<const int>; 112 static_assert(testConstexprSpan<Sp, 0>(Sp{}), ""); 113 114 static_assert(testConstexprSpan<Sp, 0, 4>(Sp{carr1}), ""); 115 static_assert(testConstexprSpan<Sp, 0, 3>(Sp{carr1}), ""); 116 static_assert(testConstexprSpan<Sp, 0, 2>(Sp{carr1}), ""); 117 static_assert(testConstexprSpan<Sp, 0, 1>(Sp{carr1}), ""); 118 static_assert(testConstexprSpan<Sp, 0, 0>(Sp{carr1}), ""); 119 120 static_assert(testConstexprSpan<Sp, 1, 3>(Sp{carr1}), ""); 121 static_assert(testConstexprSpan<Sp, 2, 2>(Sp{carr1}), ""); 122 static_assert(testConstexprSpan<Sp, 3, 1>(Sp{carr1}), ""); 123 static_assert(testConstexprSpan<Sp, 4, 0>(Sp{carr1}), ""); 124 } 125 126 { 127 using Sp = std::span<const int, 4>; 128 129 static_assert(testConstexprSpan<Sp, 0, 4>(Sp{carr1}), ""); 130 static_assert(testConstexprSpan<Sp, 0, 3>(Sp{carr1}), ""); 131 static_assert(testConstexprSpan<Sp, 0, 2>(Sp{carr1}), ""); 132 static_assert(testConstexprSpan<Sp, 0, 1>(Sp{carr1}), ""); 133 static_assert(testConstexprSpan<Sp, 0, 0>(Sp{carr1}), ""); 134 135 static_assert(testConstexprSpan<Sp, 1, 3>(Sp{carr1}), ""); 136 static_assert(testConstexprSpan<Sp, 2, 2>(Sp{carr1}), ""); 137 static_assert(testConstexprSpan<Sp, 3, 1>(Sp{carr1}), ""); 138 static_assert(testConstexprSpan<Sp, 4, 0>(Sp{carr1}), ""); 139 } 140 141 { 142 using Sp = std::span<const int>; 143 static_assert(testConstexprSpan<Sp, 0>(Sp{}), ""); 144 145 static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), ""); 146 static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), ""); 147 static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), ""); 148 static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), ""); 149 static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), ""); 150 } 151 152 { 153 using Sp = std::span<const int, 4>; 154 155 static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), ""); 156 157 static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), ""); 158 static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), ""); 159 static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), ""); 160 static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), ""); 161 } 162 163 { 164 using Sp = std::span<int>; 165 testRuntimeSpan<Sp, 0>(Sp{}); 166 167 testRuntimeSpan<Sp, 0, 3>(Sp{arr1}); 168 testRuntimeSpan<Sp, 0, 2>(Sp{arr1}); 169 testRuntimeSpan<Sp, 0, 1>(Sp{arr1}); 170 testRuntimeSpan<Sp, 0, 0>(Sp{arr1}); 171 172 testRuntimeSpan<Sp, 1, 2>(Sp{arr1}); 173 testRuntimeSpan<Sp, 2, 1>(Sp{arr1}); 174 testRuntimeSpan<Sp, 3, 0>(Sp{arr1}); 175 } 176 177 { 178 using Sp = std::span<int, 3>; 179 180 testRuntimeSpan<Sp, 0, 3>(Sp{arr1}); 181 testRuntimeSpan<Sp, 0, 2>(Sp{arr1}); 182 testRuntimeSpan<Sp, 0, 1>(Sp{arr1}); 183 testRuntimeSpan<Sp, 0, 0>(Sp{arr1}); 184 185 testRuntimeSpan<Sp, 1, 2>(Sp{arr1}); 186 testRuntimeSpan<Sp, 2, 1>(Sp{arr1}); 187 testRuntimeSpan<Sp, 3, 0>(Sp{arr1}); 188 } 189 190 { 191 using Sp = std::span<int>; 192 testRuntimeSpan<Sp, 0>(Sp{}); 193 194 testRuntimeSpan<Sp, 0>(Sp{arr1}); 195 testRuntimeSpan<Sp, 1>(Sp{arr1}); 196 testRuntimeSpan<Sp, 2>(Sp{arr1}); 197 testRuntimeSpan<Sp, 3>(Sp{arr1}); 198 } 199 200 { 201 using Sp = std::span<int, 3>; 202 203 testRuntimeSpan<Sp, 0>(Sp{arr1}); 204 testRuntimeSpan<Sp, 1>(Sp{arr1}); 205 testRuntimeSpan<Sp, 2>(Sp{arr1}); 206 testRuntimeSpan<Sp, 3>(Sp{arr1}); 207 } 208 209 return 0; 210 } 211