xref: /llvm-project/libcxx/test/std/containers/views/views.span/span.cons/array.pass.cpp (revision 7f845cba2ccc2ab637b8e40fbafb9f83a2d67c70)
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     TEST_DIAGNOSTIC_PUSH
97     TEST_CLANG_DIAGNOSTIC_IGNORED("-Wdangling")
98     std::span<const int> s5 = {{1, 2}};
99 #if TEST_STD_VER >= 26
100     std::span<const int, 2> s6({1, 2});
101 #else
102     std::span<const int, 2> s6 = {{1,2}};
103 #endif
104     assert(s5.size() == 2);  // and it dangles
105     assert(s6.size() == 2);  // and it dangles
106     TEST_DIAGNOSTIC_POP
107 
108     return true;
109 }
110 
111 
112 struct A {};
113 
114 int main(int, char**)
115 {
116     testSpan<int>();
117     testSpan<double>();
118     testSpan<A>();
119     testSpan<std::string>();
120 
121     static_assert(testSpan<int>());
122     static_assert(testSpan<double>());
123     static_assert(testSpan<A>());
124 
125     checkCV();
126 
127     // Size wrong
128     {
129         static_assert(!std::is_constructible<std::span<int, 2>, int (&)[3]>::value, "");
130     }
131 
132     // Type wrong
133     {
134         static_assert(!std::is_constructible<std::span<float>,    int (&)[3]>::value, "");
135         static_assert(!std::is_constructible<std::span<float, 3>, int (&)[3]>::value, "");
136     }
137 
138     // CV wrong (dynamically sized)
139     {
140         static_assert(!std::is_constructible<std::span<int>, const int (&)[3]>::value, "");
141         static_assert(!std::is_constructible<std::span<int>, volatile int (&)[3]>::value, "");
142         static_assert(!std::is_constructible<std::span<int>, const volatile int (&)[3]>::value, "");
143 
144         static_assert(!std::is_constructible<std::span<const int>, volatile int (&)[3]>::value, "");
145         static_assert(!std::is_constructible<std::span<const int>, const volatile int (&)[3]>::value, "");
146 
147         static_assert(!std::is_constructible<std::span<volatile int>, const int (&)[3]>::value, "");
148         static_assert(!std::is_constructible<std::span<volatile int>, const volatile int (&)[3]>::value, "");
149     }
150 
151     // CV wrong (statically sized)
152     {
153         static_assert(!std::is_constructible<std::span<int, 3>, const int (&)[3]>::value, "");
154         static_assert(!std::is_constructible<std::span<int, 3>, volatile int (&)[3]>::value, "");
155         static_assert(!std::is_constructible<std::span<int, 3>, const volatile int (&)[3]>::value, "");
156 
157         static_assert(!std::is_constructible<std::span<const int, 3>, volatile int (&)[3]>::value, "");
158         static_assert(!std::is_constructible<std::span<const int, 3>, const volatile int (&)[3]>::value, "");
159 
160         static_assert(!std::is_constructible<std::span<volatile int, 3>, const int (&)[3]>::value, "");
161         static_assert(!std::is_constructible<std::span<volatile int, 3>, const volatile int (&)[3]>::value, "");
162     }
163 
164     return 0;
165 }
166