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

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