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 Count>
13 //  constexpr span<element_type, Count> first() const;
14 //
15 // constexpr span<element_type, dynamic_extent> first(size_type count) const;
16 //
17 //  Requires: Count <= size().
18 
19 
20 #include <span>
21 #include <cassert>
22 #include <algorithm>
23 #include <string>
24 
25 #include "test_macros.h"
26 
27 template <typename Span, size_t Count>
testConstexprSpan(Span sp)28 constexpr bool testConstexprSpan(Span sp)
29 {
30     LIBCPP_ASSERT((noexcept(sp.template first<Count>())));
31     LIBCPP_ASSERT((noexcept(sp.first(Count))));
32     auto s1 = sp.template first<Count>();
33     auto s2 = sp.first(Count);
34     using S1 = decltype(s1);
35     using S2 = decltype(s2);
36     ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type);
37     ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type);
38     static_assert(S1::extent == Count, "");
39     static_assert(S2::extent == std::dynamic_extent, "");
40     return
41         s1.data() == s2.data()
42      && s1.size() == s2.size()
43      && std::equal(s1.begin(), s1.end(), sp.begin());
44 }
45 
46 
47 template <typename Span, size_t Count>
testRuntimeSpan(Span sp)48 void testRuntimeSpan(Span sp)
49 {
50     LIBCPP_ASSERT((noexcept(sp.template first<Count>())));
51     LIBCPP_ASSERT((noexcept(sp.first(Count))));
52     auto s1 = sp.template first<Count>();
53     auto s2 = sp.first(Count);
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 == Count, "");
59     static_assert(S2::extent == std::dynamic_extent, "");
60     assert(s1.data() == s2.data());
61     assert(s1.size() == s2.size());
62     assert(std::equal(s1.begin(), s1.end(), sp.begin()));
63 }
64 
65 
66 constexpr int carr1[] = {1,2,3,4};
67           int   arr[] = {5,6,7};
68 std::string   sarr [] = { "ABC", "DEF", "GHI", "JKL", "MNO"};
69 
main(int,char **)70 int main(int, char**)
71 {
72     {
73     using Sp = std::span<const int>;
74     static_assert(testConstexprSpan<Sp, 0>(Sp{}), "");
75 
76     static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), "");
77     static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), "");
78     static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), "");
79     static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), "");
80     static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), "");
81     }
82 
83     {
84     using Sp = std::span<const int, 4>;
85 
86     static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), "");
87     static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), "");
88     static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), "");
89     static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), "");
90     static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), "");
91     }
92 
93     {
94     using Sp = std::span<int>;
95     testRuntimeSpan<Sp, 0>(Sp{});
96 
97     testRuntimeSpan<Sp, 0>(Sp{arr});
98     testRuntimeSpan<Sp, 1>(Sp{arr});
99     testRuntimeSpan<Sp, 2>(Sp{arr});
100     testRuntimeSpan<Sp, 3>(Sp{arr});
101     }
102 
103     {
104     using Sp = std::span<int, 3>;
105 
106     testRuntimeSpan<Sp, 0>(Sp{arr});
107     testRuntimeSpan<Sp, 1>(Sp{arr});
108     testRuntimeSpan<Sp, 2>(Sp{arr});
109     testRuntimeSpan<Sp, 3>(Sp{arr});
110     }
111 
112     {
113     using Sp = std::span<std::string>;
114     testConstexprSpan<Sp, 0>(Sp{});
115 
116     testRuntimeSpan<Sp, 0>(Sp{sarr});
117     testRuntimeSpan<Sp, 1>(Sp{sarr});
118     testRuntimeSpan<Sp, 2>(Sp{sarr});
119     testRuntimeSpan<Sp, 3>(Sp{sarr});
120     testRuntimeSpan<Sp, 4>(Sp{sarr});
121     testRuntimeSpan<Sp, 5>(Sp{sarr});
122     }
123 
124     {
125     using Sp = std::span<std::string, 5>;
126 
127     testRuntimeSpan<Sp, 0>(Sp{sarr});
128     testRuntimeSpan<Sp, 1>(Sp{sarr});
129     testRuntimeSpan<Sp, 2>(Sp{sarr});
130     testRuntimeSpan<Sp, 3>(Sp{sarr});
131     testRuntimeSpan<Sp, 4>(Sp{sarr});
132     testRuntimeSpan<Sp, 5>(Sp{sarr});
133     }
134 
135   return 0;
136 }
137