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
9// Test all the ways of initializing a std::array.
10
11#include <array>
12#include <cassert>
13#include <type_traits>
14#include "test_macros.h"
15
16struct NoDefault {
17 TEST_CONSTEXPR NoDefault(int) {}
18};
19
20struct test_initialization {
21 template <typename T>
22 TEST_CONSTEXPR_CXX14 void operator()() const {
23 // Check default initalization
24 {
25 std::array<T, 0> a0;
26 (void)a0;
27 // Before C++20, default initialization doesn't work inside constexpr for
28 // trivially default constructible types. This only apply to non-empty arrays,
29 // since empty arrays don't hold an element of type T.
30#if TEST_STD_VER < 20
31 if (!(TEST_IS_CONSTANT_EVALUATED && std::is_trivially_default_constructible<T>::value))
32#endif
33 {
34 std::array<T, 1> a1;
35 (void)a1;
36 std::array<T, 2> a2;
37 (void)a2;
38 std::array<T, 3> a3;
39 (void)a3;
40 }
41
42 std::array<NoDefault, 0> nodefault;
43 (void)nodefault;
44 }
45
46 // A const empty array can also be default-initialized regardless of the type
47 // it contains. For non-empty arrays, this doesn't work whenever T doesn't
48 // have a user-provided default constructor.
49 {
50 const std::array<T, 0> a0;
51 (void)a0;
52 const std::array<NoDefault, 0> nodefault;
53 (void)nodefault;
54 }
55
56 // Check direct-list-initialization syntax (introduced in C++11)
57#if TEST_STD_VER >= 11
58 {
59 {
60 std::array<T, 0> a0_0{};
61 (void)a0_0;
62 }
63 {
64 std::array<T, 1> a1_0{};
65 (void)a1_0;
66 std::array<T, 1> a1_1{T()};
67 (void)a1_1;
68 }
69 {
70 std::array<T, 2> a2_0{};
71 (void)a2_0;
72 std::array<T, 2> a2_1{T()};
73 (void)a2_1;
74 std::array<T, 2> a2_2{T(), T()};
75 (void)a2_2;
76 }
77 {
78 std::array<T, 3> a3_0{};
79 (void)a3_0;
80 std::array<T, 3> a3_1{T()};
81 (void)a3_1;
82 std::array<T, 3> a3_2{T(), T()};
83 (void)a3_2;
84 std::array<T, 3> a3_3{T(), T(), T()};
85 (void)a3_3;
86 }
87
88 std::array<NoDefault, 0> nodefault{};
89 (void)nodefault;
90 }
91#endif
92
93 // Check copy-list-initialization syntax
94 {
95 {
96 std::array<T, 0> a0_0 = {};
97 (void)a0_0;
98 }
99 {
100 std::array<T, 1> a1_0 = {};
101 (void)a1_0;
102 std::array<T, 1> a1_1 = {T()};
103 (void)a1_1;
104 }
105 {
106 std::array<T, 2> a2_0 = {};
107 (void)a2_0;
108 std::array<T, 2> a2_1 = {T()};
109 (void)a2_1;
110 std::array<T, 2> a2_2 = {T(), T()};
111 (void)a2_2;
112 }
113 {
114 std::array<T, 3> a3_0 = {};
115 (void)a3_0;
116 std::array<T, 3> a3_1 = {T()};
117 (void)a3_1;
118 std::array<T, 3> a3_2 = {T(), T()};
119 (void)a3_2;
120 std::array<T, 3> a3_3 = {T(), T(), T()};
121 (void)a3_3;
122 }
123
124 std::array<NoDefault, 0> nodefault = {};
125 (void)nodefault;
126 }
127
128 // Test aggregate initialization
129 {
130 {
131 std::array<T, 0> a0_0 = {{}};
132 (void)a0_0;
133 }
134 {
135 std::array<T, 1> a1_0 = {{}};
136 (void)a1_0;
137 std::array<T, 1> a1_1 = {{T()}};
138 (void)a1_1;
139 }
140 {
141 std::array<T, 2> a2_0 = {{}};
142 (void)a2_0;
143 std::array<T, 2> a2_1 = {{T()}};
144 (void)a2_1;
145 std::array<T, 2> a2_2 = {{T(), T()}};
146 (void)a2_2;
147 }
148 {
149 std::array<T, 3> a3_0 = {{}};
150 (void)a3_0;
151 std::array<T, 3> a3_1 = {{T()}};
152 (void)a3_1;
153 std::array<T, 3> a3_2 = {{T(), T()}};
154 (void)a3_2;
155 std::array<T, 3> a3_3 = {{T(), T(), T()}};
156 (void)a3_3;
157 }
158
159 // See http://wg21.link/LWG2157
160 std::array<NoDefault, 0> nodefault = {._M_elems: {}};
161 (void)nodefault;
162 }
163 }
164};
165
166// Test construction from an initializer-list
167TEST_CONSTEXPR_CXX14 bool test_initializer_list() {
168 {
169 std::array<double, 3> const a3_0 = {};
170 assert(a3_0[0] == double());
171 assert(a3_0[1] == double());
172 assert(a3_0[2] == double());
173 }
174 {
175 std::array<double, 3> const a3_1 = {1};
176 assert(a3_1[0] == double(1));
177 assert(a3_1[1] == double());
178 assert(a3_1[2] == double());
179 }
180 {
181 std::array<double, 3> const a3_2 = {1, 2.2};
182 assert(a3_2[0] == double(1));
183 assert(a3_2[1] == 2.2);
184 assert(a3_2[2] == double());
185 }
186 {
187 std::array<double, 3> const a3_3 = {1, 2, 3.5};
188 assert(a3_3[0] == double(1));
189 assert(a3_3[1] == double(2));
190 assert(a3_3[2] == 3.5);
191 }
192
193 return true;
194}
195
196struct Empty {};
197struct Trivial {
198 int i;
199 int j;
200};
201struct NonTrivial {
202 TEST_CONSTEXPR NonTrivial() {}
203 TEST_CONSTEXPR NonTrivial(NonTrivial const&) {}
204};
205struct NonEmptyNonTrivial {
206 int i;
207 int j;
208 TEST_CONSTEXPR NonEmptyNonTrivial() : i(22), j(33) {}
209 TEST_CONSTEXPR NonEmptyNonTrivial(NonEmptyNonTrivial const&) : i(22), j(33) {}
210};
211
212template <typename F>
213TEST_CONSTEXPR_CXX14 bool with_all_types() {
214 F().template operator()<char>();
215 F().template operator()<int>();
216 F().template operator()<long>();
217 F().template operator()<float>();
218 F().template operator()<double>();
219 F().template operator()<long double>();
220 F().template operator()<Empty>();
221 F().template operator()<Trivial>();
222 F().template operator()<NonTrivial>();
223 F().template operator()<NonEmptyNonTrivial>();
224 return true;
225}
226
227// This is a regression test -- previously, libc++ would implement empty arrays by
228// storing an array of characters, which means that the array would be initializable
229// from nonsense like an integer (or anything else that can be narrowed to char).
230#if TEST_STD_VER >= 20
231template <class T>
232concept is_list_initializable_int = requires {
233 { T{123} };
234};
235
236struct Foo {};
237static_assert(!is_list_initializable_int<std::array<Foo, 0>>);
238static_assert(!is_list_initializable_int<std::array<Foo, 1>>);
239#endif
240
241int main(int, char**) {
242 with_all_types<test_initialization>();
243 test_initializer_list();
244#if TEST_STD_VER >= 14
245 static_assert(with_all_types<test_initialization>(), "");
246 static_assert(test_initializer_list(), "");
247#endif
248
249 return 0;
250}
251

source code of libcxx/test/std/containers/sequences/array/array.cons/initialization.pass.cpp