xref: /llvm-project/libcxx/test/std/containers/sequences/array/array.cons/initialization.pass.cpp (revision 1c7607e8ee6ec4ca3abce1561dd39a98d4efac96)
17265ff92SLouis Dionne //===----------------------------------------------------------------------===//
27265ff92SLouis Dionne //
37265ff92SLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47265ff92SLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
57265ff92SLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67265ff92SLouis Dionne //
77265ff92SLouis Dionne //===----------------------------------------------------------------------===//
87265ff92SLouis Dionne 
97265ff92SLouis Dionne // Test all the ways of initializing a std::array.
107265ff92SLouis Dionne 
117265ff92SLouis Dionne #include <array>
127265ff92SLouis Dionne #include <cassert>
137265ff92SLouis Dionne #include <type_traits>
147265ff92SLouis Dionne #include "test_macros.h"
157265ff92SLouis Dionne 
167265ff92SLouis Dionne 
177265ff92SLouis Dionne struct NoDefault {
NoDefaultNoDefault187265ff92SLouis Dionne     TEST_CONSTEXPR NoDefault(int) { }
197265ff92SLouis Dionne };
207265ff92SLouis Dionne 
2170bcd81eSLouis Dionne struct test_initialization {
227265ff92SLouis Dionne     template <typename T>
operator ()test_initialization237265ff92SLouis Dionne     TEST_CONSTEXPR_CXX14 void operator()() const
247265ff92SLouis Dionne     {
2570bcd81eSLouis Dionne         // Check default initalization
2670bcd81eSLouis Dionne         {
2770bcd81eSLouis Dionne             std::array<T, 0> a0; (void)a0;
2870bcd81eSLouis Dionne             // Before C++20, default initialization doesn't work inside constexpr for
2970bcd81eSLouis Dionne             // trivially default constructible types. This only apply to non-empty arrays,
3070bcd81eSLouis Dionne             // since empty arrays don't hold an element of type T.
31*1c7607e8SStephan T. Lavavej #if TEST_STD_VER < 20
32*1c7607e8SStephan T. Lavavej             if (!(TEST_IS_CONSTANT_EVALUATED && std::is_trivially_default_constructible<T>::value))
33*1c7607e8SStephan T. Lavavej #endif
34*1c7607e8SStephan T. Lavavej             {
35*1c7607e8SStephan T. Lavavej               std::array<T, 1> a1;
36*1c7607e8SStephan T. Lavavej               (void)a1;
37*1c7607e8SStephan T. Lavavej               std::array<T, 2> a2;
38*1c7607e8SStephan T. Lavavej               (void)a2;
39*1c7607e8SStephan T. Lavavej               std::array<T, 3> a3;
40*1c7607e8SStephan T. Lavavej               (void)a3;
4170bcd81eSLouis Dionne             }
4270bcd81eSLouis Dionne 
4370bcd81eSLouis Dionne             std::array<NoDefault, 0> nodefault; (void)nodefault;
4470bcd81eSLouis Dionne         }
4570bcd81eSLouis Dionne 
4670bcd81eSLouis Dionne         // A const empty array can also be default-initialized regardless of the type
4770bcd81eSLouis Dionne         // it contains. For non-empty arrays, this doesn't work whenever T doesn't
4870bcd81eSLouis Dionne         // have a user-provided default constructor.
4970bcd81eSLouis Dionne         {
5070bcd81eSLouis Dionne             const std::array<T, 0> a0; (void)a0;
5170bcd81eSLouis Dionne             const std::array<NoDefault, 0> nodefault; (void)nodefault;
5270bcd81eSLouis Dionne         }
5370bcd81eSLouis Dionne 
547265ff92SLouis Dionne         // Check direct-list-initialization syntax (introduced in C++11)
557265ff92SLouis Dionne     #if TEST_STD_VER >= 11
567265ff92SLouis Dionne         {
577265ff92SLouis Dionne             {
587265ff92SLouis Dionne                 std::array<T, 0> a0_0{}; (void)a0_0;
597265ff92SLouis Dionne             }
607265ff92SLouis Dionne             {
617265ff92SLouis Dionne                 std::array<T, 1> a1_0{}; (void)a1_0;
627265ff92SLouis Dionne                 std::array<T, 1> a1_1{T()}; (void)a1_1;
637265ff92SLouis Dionne             }
647265ff92SLouis Dionne             {
657265ff92SLouis Dionne                 std::array<T, 2> a2_0{}; (void)a2_0;
667265ff92SLouis Dionne                 std::array<T, 2> a2_1{T()}; (void)a2_1;
677265ff92SLouis Dionne                 std::array<T, 2> a2_2{T(), T()}; (void)a2_2;
687265ff92SLouis Dionne             }
697265ff92SLouis Dionne             {
707265ff92SLouis Dionne                 std::array<T, 3> a3_0{}; (void)a3_0;
717265ff92SLouis Dionne                 std::array<T, 3> a3_1{T()}; (void)a3_1;
727265ff92SLouis Dionne                 std::array<T, 3> a3_2{T(), T()}; (void)a3_2;
737265ff92SLouis Dionne                 std::array<T, 3> a3_3{T(), T(), T()}; (void)a3_3;
747265ff92SLouis Dionne             }
757265ff92SLouis Dionne 
767265ff92SLouis Dionne             std::array<NoDefault, 0> nodefault{}; (void)nodefault;
777265ff92SLouis Dionne         }
787265ff92SLouis Dionne     #endif
797265ff92SLouis Dionne 
807265ff92SLouis Dionne         // Check copy-list-initialization syntax
817265ff92SLouis Dionne         {
827265ff92SLouis Dionne             {
837265ff92SLouis Dionne                 std::array<T, 0> a0_0 = {}; (void)a0_0;
847265ff92SLouis Dionne             }
857265ff92SLouis Dionne             {
867265ff92SLouis Dionne                 std::array<T, 1> a1_0 = {}; (void)a1_0;
877265ff92SLouis Dionne                 std::array<T, 1> a1_1 = {T()}; (void)a1_1;
887265ff92SLouis Dionne             }
897265ff92SLouis Dionne             {
907265ff92SLouis Dionne                 std::array<T, 2> a2_0 = {}; (void)a2_0;
917265ff92SLouis Dionne                 std::array<T, 2> a2_1 = {T()}; (void)a2_1;
927265ff92SLouis Dionne                 std::array<T, 2> a2_2 = {T(), T()}; (void)a2_2;
937265ff92SLouis Dionne             }
947265ff92SLouis Dionne             {
957265ff92SLouis Dionne                 std::array<T, 3> a3_0 = {}; (void)a3_0;
967265ff92SLouis Dionne                 std::array<T, 3> a3_1 = {T()}; (void)a3_1;
977265ff92SLouis Dionne                 std::array<T, 3> a3_2 = {T(), T()}; (void)a3_2;
987265ff92SLouis Dionne                 std::array<T, 3> a3_3 = {T(), T(), T()}; (void)a3_3;
997265ff92SLouis Dionne             }
1007265ff92SLouis Dionne 
1017265ff92SLouis Dionne             std::array<NoDefault, 0> nodefault = {}; (void)nodefault;
1027265ff92SLouis Dionne         }
1037265ff92SLouis Dionne 
1047265ff92SLouis Dionne         // Test aggregate initialization
1057265ff92SLouis Dionne         {
1067265ff92SLouis Dionne             {
1077265ff92SLouis Dionne                 std::array<T, 0> a0_0 = {{}}; (void)a0_0;
1087265ff92SLouis Dionne             }
1097265ff92SLouis Dionne             {
1107265ff92SLouis Dionne                 std::array<T, 1> a1_0 = {{}}; (void)a1_0;
1117265ff92SLouis Dionne                 std::array<T, 1> a1_1 = {{T()}}; (void)a1_1;
1127265ff92SLouis Dionne             }
1137265ff92SLouis Dionne             {
1147265ff92SLouis Dionne                 std::array<T, 2> a2_0 = {{}}; (void)a2_0;
1157265ff92SLouis Dionne                 std::array<T, 2> a2_1 = {{T()}}; (void)a2_1;
1167265ff92SLouis Dionne                 std::array<T, 2> a2_2 = {{T(), T()}}; (void)a2_2;
1177265ff92SLouis Dionne             }
1187265ff92SLouis Dionne             {
1197265ff92SLouis Dionne                 std::array<T, 3> a3_0 = {{}}; (void)a3_0;
1207265ff92SLouis Dionne                 std::array<T, 3> a3_1 = {{T()}}; (void)a3_1;
1217265ff92SLouis Dionne                 std::array<T, 3> a3_2 = {{T(), T()}}; (void)a3_2;
1227265ff92SLouis Dionne                 std::array<T, 3> a3_3 = {{T(), T(), T()}}; (void)a3_3;
1237265ff92SLouis Dionne             }
1247265ff92SLouis Dionne 
1257265ff92SLouis Dionne             // See http://wg21.link/LWG2157
1267265ff92SLouis Dionne             std::array<NoDefault, 0> nodefault = {{}}; (void)nodefault;
1277265ff92SLouis Dionne         }
1287265ff92SLouis Dionne     }
1297265ff92SLouis Dionne };
1307265ff92SLouis Dionne 
1317265ff92SLouis Dionne // Test construction from an initializer-list
test_initializer_list()1327265ff92SLouis Dionne TEST_CONSTEXPR_CXX14 bool test_initializer_list()
1337265ff92SLouis Dionne {
1347265ff92SLouis Dionne     {
1357265ff92SLouis Dionne         std::array<double, 3> const a3_0 = {};
1367265ff92SLouis Dionne         assert(a3_0[0] == double());
1377265ff92SLouis Dionne         assert(a3_0[1] == double());
1387265ff92SLouis Dionne         assert(a3_0[2] == double());
1397265ff92SLouis Dionne     }
1407265ff92SLouis Dionne     {
1417265ff92SLouis Dionne         std::array<double, 3> const a3_1 = {1};
1427265ff92SLouis Dionne         assert(a3_1[0] == double(1));
1437265ff92SLouis Dionne         assert(a3_1[1] == double());
1447265ff92SLouis Dionne         assert(a3_1[2] == double());
1457265ff92SLouis Dionne     }
1467265ff92SLouis Dionne     {
1477265ff92SLouis Dionne         std::array<double, 3> const a3_2 = {1, 2.2};
1487265ff92SLouis Dionne         assert(a3_2[0] == double(1));
1497265ff92SLouis Dionne         assert(a3_2[1] == 2.2);
1507265ff92SLouis Dionne         assert(a3_2[2] == double());
1517265ff92SLouis Dionne     }
1527265ff92SLouis Dionne     {
1537265ff92SLouis Dionne         std::array<double, 3> const a3_3 = {1, 2, 3.5};
1547265ff92SLouis Dionne         assert(a3_3[0] == double(1));
1557265ff92SLouis Dionne         assert(a3_3[1] == double(2));
1567265ff92SLouis Dionne         assert(a3_3[2] == 3.5);
1577265ff92SLouis Dionne     }
1587265ff92SLouis Dionne 
1597265ff92SLouis Dionne     return true;
1607265ff92SLouis Dionne }
1617265ff92SLouis Dionne 
1627265ff92SLouis Dionne struct Empty { };
1637265ff92SLouis Dionne struct Trivial { int i; int j; };
1647265ff92SLouis Dionne struct NonTrivial {
NonTrivialNonTrivial1657265ff92SLouis Dionne     TEST_CONSTEXPR NonTrivial() { }
NonTrivialNonTrivial1667265ff92SLouis Dionne     TEST_CONSTEXPR NonTrivial(NonTrivial const&) { }
1677265ff92SLouis Dionne };
1687265ff92SLouis Dionne struct NonEmptyNonTrivial {
1697265ff92SLouis Dionne     int i; int j;
NonEmptyNonTrivialNonEmptyNonTrivial1707265ff92SLouis Dionne     TEST_CONSTEXPR NonEmptyNonTrivial() : i(22), j(33) { }
NonEmptyNonTrivialNonEmptyNonTrivial1717265ff92SLouis Dionne     TEST_CONSTEXPR NonEmptyNonTrivial(NonEmptyNonTrivial const&) : i(22), j(33) { }
1727265ff92SLouis Dionne };
1737265ff92SLouis Dionne 
1747265ff92SLouis Dionne template <typename F>
with_all_types()1757265ff92SLouis Dionne TEST_CONSTEXPR_CXX14 bool with_all_types()
1767265ff92SLouis Dionne {
1777265ff92SLouis Dionne     F().template operator()<char>();
1787265ff92SLouis Dionne     F().template operator()<int>();
1797265ff92SLouis Dionne     F().template operator()<long>();
1807265ff92SLouis Dionne     F().template operator()<float>();
1817265ff92SLouis Dionne     F().template operator()<double>();
1827265ff92SLouis Dionne     F().template operator()<long double>();
1837265ff92SLouis Dionne     F().template operator()<Empty>();
1847265ff92SLouis Dionne     F().template operator()<Trivial>();
1857265ff92SLouis Dionne     F().template operator()<NonTrivial>();
1867265ff92SLouis Dionne     F().template operator()<NonEmptyNonTrivial>();
1877265ff92SLouis Dionne     return true;
1887265ff92SLouis Dionne }
1897265ff92SLouis Dionne 
19070bcd81eSLouis Dionne // This is a regression test -- previously, libc++ would implement empty arrays by
19170bcd81eSLouis Dionne // storing an array of characters, which means that the array would be initializable
19270bcd81eSLouis Dionne // from nonsense like an integer (or anything else that can be narrowed to char).
19370bcd81eSLouis Dionne #if TEST_STD_VER >= 20
19470bcd81eSLouis Dionne template <class T>
19570bcd81eSLouis Dionne concept is_list_initializable_int = requires {
19670bcd81eSLouis Dionne     { T{123} };
19770bcd81eSLouis Dionne };
19870bcd81eSLouis Dionne 
19970bcd81eSLouis Dionne struct Foo { };
20070bcd81eSLouis Dionne static_assert(!is_list_initializable_int<std::array<Foo, 0>>);
20170bcd81eSLouis Dionne static_assert(!is_list_initializable_int<std::array<Foo, 1>>);
20270bcd81eSLouis Dionne #endif
20370bcd81eSLouis Dionne 
main(int,char **)2047265ff92SLouis Dionne int main(int, char**)
2057265ff92SLouis Dionne {
20670bcd81eSLouis Dionne     with_all_types<test_initialization>();
2077265ff92SLouis Dionne     test_initializer_list();
2087265ff92SLouis Dionne #if TEST_STD_VER >= 14
20970bcd81eSLouis Dionne     static_assert(with_all_types<test_initialization>(), "");
2107265ff92SLouis Dionne     static_assert(test_initializer_list(), "");
2117265ff92SLouis Dionne #endif
2127265ff92SLouis Dionne 
2137265ff92SLouis Dionne     return 0;
2147265ff92SLouis Dionne }
215