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