1 // -*- C++ -*-
2 //===------------------------------ span ---------------------------------===//
3 //
4 // The LLVM Compiler Infrastructure
5 //
6 // This file is dual licensed under the MIT and the University of Illinois Open
7 // Source Licenses. See LICENSE.TXT for details.
8 //
9 //===---------------------------------------------------------------------===//
10 // UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
11
12 // <span>
13
14 // template<class OtherElementType, ptrdiff_t OtherExtent>
15 // constexpr span(const span<OtherElementType, OtherExtent>& s) noexcept;
16 //
17 // Remarks: This constructor shall not participate in overload resolution unless:
18 // Extent == dynamic_extent || Extent == OtherExtent is true, and
19 // OtherElementType(*)[] is convertible to ElementType(*)[].
20
21
22 #include <span>
23 #include <cassert>
24 #include <string>
25
26 #include "test_macros.h"
27
checkCV()28 void checkCV()
29 {
30 std::span< int> sp;
31 // std::span<const int> csp;
32 std::span< volatile int> vsp;
33 // std::span<const volatile int> cvsp;
34
35 std::span< int, 0> sp0;
36 // std::span<const int, 0> csp0;
37 std::span< volatile int, 0> vsp0;
38 // std::span<const volatile int, 0> cvsp0;
39
40 // dynamic -> dynamic
41 {
42 std::span<const int> s1{ sp}; // a span<const int> pointing at int.
43 std::span< volatile int> s2{ sp}; // a span< volatile int> pointing at int.
44 std::span<const volatile int> s3{ sp}; // a span<const volatile int> pointing at int.
45 std::span<const volatile int> s4{ vsp}; // a span<const volatile int> pointing at volatile int.
46 assert(s1.size() + s2.size() + s3.size() + s4.size() == 0);
47 }
48
49 // static -> static
50 {
51 std::span<const int, 0> s1{ sp0}; // a span<const int> pointing at int.
52 std::span< volatile int, 0> s2{ sp0}; // a span< volatile int> pointing at int.
53 std::span<const volatile int, 0> s3{ sp0}; // a span<const volatile int> pointing at int.
54 std::span<const volatile int, 0> s4{ vsp0}; // a span<const volatile int> pointing at volatile int.
55 assert(s1.size() + s2.size() + s3.size() + s4.size() == 0);
56 }
57
58 // static -> dynamic
59 {
60 std::span<const int> s1{ sp0}; // a span<const int> pointing at int.
61 std::span< volatile int> s2{ sp0}; // a span< volatile int> pointing at int.
62 std::span<const volatile int> s3{ sp0}; // a span<const volatile int> pointing at int.
63 std::span<const volatile int> s4{ vsp0}; // a span<const volatile int> pointing at volatile int.
64 assert(s1.size() + s2.size() + s3.size() + s4.size() == 0);
65 }
66
67 // dynamic -> static
68 {
69 std::span<const int, 0> s1{ sp}; // a span<const int> pointing at int.
70 std::span< volatile int, 0> s2{ sp}; // a span< volatile int> pointing at int.
71 std::span<const volatile int, 0> s3{ sp}; // a span<const volatile int> pointing at int.
72 std::span<const volatile int, 0> s4{ vsp}; // a span<const volatile int> pointing at volatile int.
73 assert(s1.size() + s2.size() + s3.size() + s4.size() == 0);
74 }
75 }
76
77
78 template <typename T>
testConstexprSpan()79 constexpr bool testConstexprSpan()
80 {
81 std::span<T> s0{};
82 std::span<T, 0> s1(s0); // dynamic -> static
83 std::span<T> s2(s1); // static -> dynamic
84 ASSERT_NOEXCEPT(std::span<T> {s0});
85 ASSERT_NOEXCEPT(std::span<T, 0>{s1});
86 ASSERT_NOEXCEPT(std::span<T> {s1});
87 ASSERT_NOEXCEPT(std::span<T, 0>{s0});
88
89 return
90 s1.data() == nullptr && s1.size() == 0
91 && s2.data() == nullptr && s2.size() == 0;
92 }
93
94
95 template <typename T>
testRuntimeSpan()96 void testRuntimeSpan()
97 {
98 std::span<T> s0{};
99 std::span<T, 0> s1(s0); // dynamic -> static
100 std::span<T> s2(s1); // static -> dynamic
101 ASSERT_NOEXCEPT(std::span<T> {s0});
102 ASSERT_NOEXCEPT(std::span<T, 0>{s1});
103 ASSERT_NOEXCEPT(std::span<T> {s1});
104 ASSERT_NOEXCEPT(std::span<T, 0>{s0});
105
106 assert(s1.data() == nullptr && s1.size() == 0);
107 assert(s2.data() == nullptr && s2.size() == 0);
108 }
109
110
111 template <typename Dest, typename Src>
testConversionSpan()112 bool testConversionSpan()
113 {
114 static_assert(std::is_convertible_v<Src(*)[], Dest(*)[]>, "Bad input types to 'testConversionSpan");
115 std::span<Src> s0d{};
116 std::span<Src> s0s{};
117 std::span<Dest, 0> s1(s0d); // dynamic -> static
118 std::span<Dest> s2(s0s); // static -> dynamic
119 s1.data() == nullptr && s1.size() == 0
120 && s2.data() == nullptr && s2.size() == 0;
121 }
122
123 struct A{};
124
main()125 int main ()
126 {
127 static_assert(testConstexprSpan<int>(), "");
128 static_assert(testConstexprSpan<long>(), "");
129 static_assert(testConstexprSpan<double>(), "");
130 static_assert(testConstexprSpan<A>(), "");
131
132 testRuntimeSpan<int>();
133 testRuntimeSpan<long>();
134 testRuntimeSpan<double>();
135 testRuntimeSpan<std::string>();
136 testRuntimeSpan<A>();
137
138 // TODO: Add some conversion tests here that aren't "X --> const X"
139 // assert((testConversionSpan<unsigned char, char>()));
140
141 checkCV();
142 }
143