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 N> |
13 | // constexpr span(element_type (&arr)[N]) noexcept; |
14 | // |
15 | // Remarks: These constructors shall not participate in overload resolution unless: |
16 | // - extent == dynamic_extent || N == extent is true, and |
17 | // - remove_pointer_t<decltype(data(arr))>(*)[] is convertible to ElementType(*)[]. |
18 | // |
19 | |
20 | #include <cassert> |
21 | #include <span> |
22 | #include <string> |
23 | #include <type_traits> |
24 | |
25 | #include "test_macros.h" |
26 | |
27 | |
28 | void checkCV() |
29 | { |
30 | int arr[] = {1,2,3}; |
31 | const int carr[] = {4,5,6}; |
32 | volatile int varr[] = {7,8,9}; |
33 | const volatile int cvarr[] = {1,3,5}; |
34 | |
35 | // Types the same (dynamic sized) |
36 | { |
37 | std::span< int> s1{ arr}; // a span< int> pointing at int. |
38 | std::span<const int> s2{ carr}; // a span<const int> pointing at const int. |
39 | std::span< volatile int> s3{ varr}; // a span< volatile int> pointing at volatile int. |
40 | std::span<const volatile int> s4{cvarr}; // a span<const volatile int> pointing at const volatile int. |
41 | assert(s1.size() + s2.size() + s3.size() + s4.size() == 12); |
42 | } |
43 | |
44 | // Types the same (static sized) |
45 | { |
46 | std::span< int,3> s1{ arr}; // a span< int> pointing at int. |
47 | std::span<const int,3> s2{ carr}; // a span<const int> pointing at const int. |
48 | std::span< volatile int,3> s3{ varr}; // a span< volatile int> pointing at volatile int. |
49 | std::span<const volatile int,3> s4{cvarr}; // a span<const volatile int> pointing at const volatile int. |
50 | assert(s1.size() + s2.size() + s3.size() + s4.size() == 12); |
51 | } |
52 | |
53 | |
54 | // types different (dynamic sized) |
55 | { |
56 | std::span<const int> s1{ arr}; // a span<const int> pointing at int. |
57 | std::span< volatile int> s2{ arr}; // a span< volatile int> pointing at int. |
58 | std::span< volatile int> s3{ arr}; // a span< volatile int> pointing at const int. |
59 | std::span<const volatile int> s4{ arr}; // a span<const volatile int> pointing at int. |
60 | std::span<const volatile int> s5{carr}; // a span<const volatile int> pointing at const int. |
61 | std::span<const volatile int> s6{varr}; // a span<const volatile int> pointing at volatile int. |
62 | assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18); |
63 | } |
64 | |
65 | // types different (static sized) |
66 | { |
67 | std::span<const int,3> s1{ arr}; // a span<const int> pointing at int. |
68 | std::span< volatile int,3> s2{ arr}; // a span< volatile int> pointing at int. |
69 | std::span< volatile int,3> s3{ arr}; // a span< volatile int> pointing at const int. |
70 | std::span<const volatile int,3> s4{ arr}; // a span<const volatile int> pointing at int. |
71 | std::span<const volatile int,3> s5{carr}; // a span<const volatile int> pointing at const int. |
72 | std::span<const volatile int,3> s6{varr}; // a span<const volatile int> pointing at volatile int. |
73 | assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18); |
74 | } |
75 | } |
76 | |
77 | template<class T> |
78 | constexpr bool testSpan() |
79 | { |
80 | T val[2] = {}; |
81 | |
82 | ASSERT_NOEXCEPT(std::span<T>{val}); |
83 | ASSERT_NOEXCEPT(std::span<T, 2>{val}); |
84 | ASSERT_NOEXCEPT(std::span<const T>{val}); |
85 | ASSERT_NOEXCEPT(std::span<const T, 2>{val}); |
86 | |
87 | std::span<T> s1 = val; |
88 | std::span<T, 2> s2 = val; |
89 | std::span<const T> s3 = val; |
90 | std::span<const T, 2> s4 = val; |
91 | assert(s1.data() == val && s1.size() == 2); |
92 | assert(s2.data() == val && s2.size() == 2); |
93 | assert(s3.data() == val && s3.size() == 2); |
94 | assert(s4.data() == val && s4.size() == 2); |
95 | |
96 | std::span<const int> s5 = {{1,2}}; |
97 | #if TEST_STD_VER >= 26 |
98 | std::span<const int, 2> s6({1, 2}); |
99 | #else |
100 | std::span<const int, 2> s6 = {{1,2}}; |
101 | #endif |
102 | assert(s5.size() == 2); // and it dangles |
103 | assert(s6.size() == 2); // and it dangles |
104 | |
105 | return true; |
106 | } |
107 | |
108 | |
109 | struct A {}; |
110 | |
111 | int main(int, char**) |
112 | { |
113 | testSpan<int>(); |
114 | testSpan<double>(); |
115 | testSpan<A>(); |
116 | testSpan<std::string>(); |
117 | |
118 | static_assert(testSpan<int>()); |
119 | static_assert(testSpan<double>()); |
120 | static_assert(testSpan<A>()); |
121 | |
122 | checkCV(); |
123 | |
124 | // Size wrong |
125 | { |
126 | static_assert(!std::is_constructible<std::span<int, 2>, int (&)[3]>::value, "" ); |
127 | } |
128 | |
129 | // Type wrong |
130 | { |
131 | static_assert(!std::is_constructible<std::span<float>, int (&)[3]>::value, "" ); |
132 | static_assert(!std::is_constructible<std::span<float, 3>, int (&)[3]>::value, "" ); |
133 | } |
134 | |
135 | // CV wrong (dynamically sized) |
136 | { |
137 | static_assert(!std::is_constructible<std::span<int>, const int (&)[3]>::value, "" ); |
138 | static_assert(!std::is_constructible<std::span<int>, volatile int (&)[3]>::value, "" ); |
139 | static_assert(!std::is_constructible<std::span<int>, const volatile int (&)[3]>::value, "" ); |
140 | |
141 | static_assert(!std::is_constructible<std::span<const int>, volatile int (&)[3]>::value, "" ); |
142 | static_assert(!std::is_constructible<std::span<const int>, const volatile int (&)[3]>::value, "" ); |
143 | |
144 | static_assert(!std::is_constructible<std::span<volatile int>, const int (&)[3]>::value, "" ); |
145 | static_assert(!std::is_constructible<std::span<volatile int>, const volatile int (&)[3]>::value, "" ); |
146 | } |
147 | |
148 | // CV wrong (statically sized) |
149 | { |
150 | static_assert(!std::is_constructible<std::span<int, 3>, const int (&)[3]>::value, "" ); |
151 | static_assert(!std::is_constructible<std::span<int, 3>, volatile int (&)[3]>::value, "" ); |
152 | static_assert(!std::is_constructible<std::span<int, 3>, const volatile int (&)[3]>::value, "" ); |
153 | |
154 | static_assert(!std::is_constructible<std::span<const int, 3>, volatile int (&)[3]>::value, "" ); |
155 | static_assert(!std::is_constructible<std::span<const int, 3>, const volatile int (&)[3]>::value, "" ); |
156 | |
157 | static_assert(!std::is_constructible<std::span<volatile int, 3>, const int (&)[3]>::value, "" ); |
158 | static_assert(!std::is_constructible<std::span<volatile int, 3>, const volatile int (&)[3]>::value, "" ); |
159 | } |
160 | |
161 | return 0; |
162 | } |
163 | |