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