1 // -*- C++ -*-
2 //===------------------------------ span ---------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===---------------------------------------------------------------------===//
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 
11 // <span>
12 
13 // template<size_t Count>
14 //  constexpr span<element_type, Count> first() const;
15 //
16 // constexpr span<element_type, dynamic_extent> first(size_type count) const;
17 //
18 //  Requires: Count <= size().
19 
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 Count>
testConstexprSpan(Span sp)29 constexpr bool testConstexprSpan(Span sp)
30 {
31     LIBCPP_ASSERT((noexcept(sp.template first<Count>())));
32     LIBCPP_ASSERT((noexcept(sp.first(Count))));
33     auto s1 = sp.template first<Count>();
34     auto s2 = sp.first(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());
45 }
46 
47 
48 template <typename Span, size_t Count>
testRuntimeSpan(Span sp)49 void testRuntimeSpan(Span sp)
50 {
51     LIBCPP_ASSERT((noexcept(sp.template first<Count>())));
52     LIBCPP_ASSERT((noexcept(sp.first(Count))));
53     auto s1 = sp.template first<Count>();
54     auto s2 = sp.first(Count);
55     using S1 = decltype(s1);
56     using S2 = decltype(s2);
57     ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
58     ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
59     static_assert(S1::extent == Count, "");
60     static_assert(S2::extent == std::dynamic_extent, "");
61     assert(s1.data() == s2.data());
62     assert(s1.size() == s2.size());
63     assert(std::equal(s1.begin(), s1.end(), sp.begin()));
64 }
65 
66 
67 constexpr int carr1[] = {1,2,3,4};
68           int   arr[] = {5,6,7};
69 std::string   sarr [] = { "ABC", "DEF", "GHI", "JKL", "MNO"};
70 
main(int,char **)71 int main(int, char**)
72 {
73     {
74     using Sp = std::span<const int>;
75     static_assert(testConstexprSpan<Sp, 0>(Sp{}), "");
76 
77     static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), "");
78     static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), "");
79     static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), "");
80     static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), "");
81     static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), "");
82     }
83 
84     {
85     using Sp = std::span<const int, 4>;
86 
87     static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), "");
88     static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), "");
89     static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), "");
90     static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), "");
91     static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), "");
92     }
93 
94     {
95     using Sp = std::span<int>;
96     testRuntimeSpan<Sp, 0>(Sp{});
97 
98     testRuntimeSpan<Sp, 0>(Sp{arr});
99     testRuntimeSpan<Sp, 1>(Sp{arr});
100     testRuntimeSpan<Sp, 2>(Sp{arr});
101     testRuntimeSpan<Sp, 3>(Sp{arr});
102     }
103 
104     {
105     using Sp = std::span<int, 3>;
106 
107     testRuntimeSpan<Sp, 0>(Sp{arr});
108     testRuntimeSpan<Sp, 1>(Sp{arr});
109     testRuntimeSpan<Sp, 2>(Sp{arr});
110     testRuntimeSpan<Sp, 3>(Sp{arr});
111     }
112 
113     {
114     using Sp = std::span<std::string>;
115     testConstexprSpan<Sp, 0>(Sp{});
116 
117     testRuntimeSpan<Sp, 0>(Sp{sarr});
118     testRuntimeSpan<Sp, 1>(Sp{sarr});
119     testRuntimeSpan<Sp, 2>(Sp{sarr});
120     testRuntimeSpan<Sp, 3>(Sp{sarr});
121     testRuntimeSpan<Sp, 4>(Sp{sarr});
122     testRuntimeSpan<Sp, 5>(Sp{sarr});
123     }
124 
125     {
126     using Sp = std::span<std::string, 5>;
127 
128     testRuntimeSpan<Sp, 0>(Sp{sarr});
129     testRuntimeSpan<Sp, 1>(Sp{sarr});
130     testRuntimeSpan<Sp, 2>(Sp{sarr});
131     testRuntimeSpan<Sp, 3>(Sp{sarr});
132     testRuntimeSpan<Sp, 4>(Sp{sarr});
133     testRuntimeSpan<Sp, 5>(Sp{sarr});
134     }
135 
136   return 0;
137 }
138