// -*- C++ -*- //===------------------------------ span ---------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===---------------------------------------------------------------------===// // UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 // <span> // template<ptrdiff_t Offset, ptrdiff_t Count = dynamic_extent> // constexpr span<element_type, see below> subspan() const; // // constexpr span<element_type, dynamic_extent> subspan( // index_type offset, index_type count = dynamic_extent) const; // // Requires: (0 <= Offset && Offset <= size()) // && (Count == dynamic_extent || Count >= 0 && Offset + Count <= size()) #include <span> #include <cassert> #include <algorithm> #include <string> #include "test_macros.h" template <typename Span, ptrdiff_t Offset, ptrdiff_t Count> constexpr bool testConstexprSpan(Span sp) { LIBCPP_ASSERT((noexcept(sp.template subspan<Offset, Count>()))); LIBCPP_ASSERT((noexcept(sp.subspan(Offset, Count)))); auto s1 = sp.template subspan<Offset, Count>(); auto s2 = sp.subspan(Offset, Count); using S1 = decltype(s1); using S2 = decltype(s2); ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Count), ""); static_assert(S2::extent == std::dynamic_extent, ""); return s1.data() == s2.data() && s1.size() == s2.size() && std::equal(s1.begin(), s1.end(), sp.begin() + Offset); } template <typename Span, ptrdiff_t Offset> constexpr bool testConstexprSpan(Span sp) { LIBCPP_ASSERT((noexcept(sp.template subspan<Offset>()))); LIBCPP_ASSERT((noexcept(sp.subspan(Offset)))); auto s1 = sp.template subspan<Offset>(); auto s2 = sp.subspan(Offset); using S1 = decltype(s1); using S2 = decltype(s2); ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Span::extent - Offset), ""); static_assert(S2::extent == std::dynamic_extent, ""); return s1.data() == s2.data() && s1.size() == s2.size() && std::equal(s1.begin(), s1.end(), sp.begin() + Offset, sp.end()); } template <typename Span, ptrdiff_t Offset, ptrdiff_t Count> void testRuntimeSpan(Span sp) { LIBCPP_ASSERT((noexcept(sp.template subspan<Offset, Count>()))); LIBCPP_ASSERT((noexcept(sp.subspan(Offset, Count)))); auto s1 = sp.template subspan<Offset, Count>(); auto s2 = sp.subspan(Offset, Count); using S1 = decltype(s1); using S2 = decltype(s2); ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Count), ""); static_assert(S2::extent == std::dynamic_extent, ""); assert(s1.data() == s2.data()); assert(s1.size() == s2.size()); assert(std::equal(s1.begin(), s1.end(), sp.begin() + Offset)); } template <typename Span, ptrdiff_t Offset> void testRuntimeSpan(Span sp) { LIBCPP_ASSERT((noexcept(sp.template subspan<Offset>()))); LIBCPP_ASSERT((noexcept(sp.subspan(Offset)))); auto s1 = sp.template subspan<Offset>(); auto s2 = sp.subspan(Offset); using S1 = decltype(s1); using S2 = decltype(s2); ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Span::extent - Offset), ""); static_assert(S2::extent == std::dynamic_extent, ""); assert(s1.data() == s2.data()); assert(s1.size() == s2.size()); assert(std::equal(s1.begin(), s1.end(), sp.begin() + Offset, sp.end())); } constexpr int carr1[] = {1,2,3,4}; int arr1[] = {5,6,7}; int main () { { using Sp = std::span<const int>; static_assert(testConstexprSpan<Sp, 0>(Sp{}), ""); static_assert(testConstexprSpan<Sp, 0, 4>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 0, 3>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 0, 2>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 0, 1>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 0, 0>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 1, 3>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 2, 2>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 3, 1>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 4, 0>(Sp{carr1}), ""); } { using Sp = std::span<const int, 4>; static_assert(testConstexprSpan<Sp, 0, 4>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 0, 3>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 0, 2>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 0, 1>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 0, 0>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 1, 3>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 2, 2>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 3, 1>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 4, 0>(Sp{carr1}), ""); } { using Sp = std::span<const int>; static_assert(testConstexprSpan<Sp, 0>(Sp{}), ""); static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), ""); } { using Sp = std::span<const int, 4>; static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), ""); static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), ""); } { using Sp = std::span<int>; testRuntimeSpan<Sp, 0>(Sp{}); testRuntimeSpan<Sp, 0, 3>(Sp{arr1}); testRuntimeSpan<Sp, 0, 2>(Sp{arr1}); testRuntimeSpan<Sp, 0, 1>(Sp{arr1}); testRuntimeSpan<Sp, 0, 0>(Sp{arr1}); testRuntimeSpan<Sp, 1, 2>(Sp{arr1}); testRuntimeSpan<Sp, 2, 1>(Sp{arr1}); testRuntimeSpan<Sp, 3, 0>(Sp{arr1}); } { using Sp = std::span<int, 3>; testRuntimeSpan<Sp, 0, 3>(Sp{arr1}); testRuntimeSpan<Sp, 0, 2>(Sp{arr1}); testRuntimeSpan<Sp, 0, 1>(Sp{arr1}); testRuntimeSpan<Sp, 0, 0>(Sp{arr1}); testRuntimeSpan<Sp, 1, 2>(Sp{arr1}); testRuntimeSpan<Sp, 2, 1>(Sp{arr1}); testRuntimeSpan<Sp, 3, 0>(Sp{arr1}); } { using Sp = std::span<int>; testRuntimeSpan<Sp, 0>(Sp{}); testRuntimeSpan<Sp, 0>(Sp{arr1}); testRuntimeSpan<Sp, 1>(Sp{arr1}); testRuntimeSpan<Sp, 2>(Sp{arr1}); testRuntimeSpan<Sp, 3>(Sp{arr1}); } { using Sp = std::span<int, 3>; testRuntimeSpan<Sp, 0>(Sp{arr1}); testRuntimeSpan<Sp, 1>(Sp{arr1}); testRuntimeSpan<Sp, 2>(Sp{arr1}); testRuntimeSpan<Sp, 3>(Sp{arr1}); } }