xref: /llvm-project/libcxx/test/std/containers/views/views.span/span.cons/array.pass.cpp (revision dbbeee6b8357c5a68543f612f3b2b607f1911b4c)
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