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