//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // Test all the ways of initializing a std::array. #include #include #include #include "test_macros.h" struct NoDefault { TEST_CONSTEXPR NoDefault(int) { } }; struct test_initialization { template TEST_CONSTEXPR_CXX14 void operator()() const { // Check default initalization { std::array a0; (void)a0; // Before C++20, default initialization doesn't work inside constexpr for // trivially default constructible types. This only apply to non-empty arrays, // since empty arrays don't hold an element of type T. #if TEST_STD_VER < 20 if (!(TEST_IS_CONSTANT_EVALUATED && std::is_trivially_default_constructible::value)) #endif { std::array a1; (void)a1; std::array a2; (void)a2; std::array a3; (void)a3; } std::array nodefault; (void)nodefault; } // A const empty array can also be default-initialized regardless of the type // it contains. For non-empty arrays, this doesn't work whenever T doesn't // have a user-provided default constructor. { const std::array a0; (void)a0; const std::array nodefault; (void)nodefault; } // Check direct-list-initialization syntax (introduced in C++11) #if TEST_STD_VER >= 11 { { std::array a0_0{}; (void)a0_0; } { std::array a1_0{}; (void)a1_0; std::array a1_1{T()}; (void)a1_1; } { std::array a2_0{}; (void)a2_0; std::array a2_1{T()}; (void)a2_1; std::array a2_2{T(), T()}; (void)a2_2; } { std::array a3_0{}; (void)a3_0; std::array a3_1{T()}; (void)a3_1; std::array a3_2{T(), T()}; (void)a3_2; std::array a3_3{T(), T(), T()}; (void)a3_3; } std::array nodefault{}; (void)nodefault; } #endif // Check copy-list-initialization syntax { { std::array a0_0 = {}; (void)a0_0; } { std::array a1_0 = {}; (void)a1_0; std::array a1_1 = {T()}; (void)a1_1; } { std::array a2_0 = {}; (void)a2_0; std::array a2_1 = {T()}; (void)a2_1; std::array a2_2 = {T(), T()}; (void)a2_2; } { std::array a3_0 = {}; (void)a3_0; std::array a3_1 = {T()}; (void)a3_1; std::array a3_2 = {T(), T()}; (void)a3_2; std::array a3_3 = {T(), T(), T()}; (void)a3_3; } std::array nodefault = {}; (void)nodefault; } // Test aggregate initialization { { std::array a0_0 = {{}}; (void)a0_0; } { std::array a1_0 = {{}}; (void)a1_0; std::array a1_1 = {{T()}}; (void)a1_1; } { std::array a2_0 = {{}}; (void)a2_0; std::array a2_1 = {{T()}}; (void)a2_1; std::array a2_2 = {{T(), T()}}; (void)a2_2; } { std::array a3_0 = {{}}; (void)a3_0; std::array a3_1 = {{T()}}; (void)a3_1; std::array a3_2 = {{T(), T()}}; (void)a3_2; std::array a3_3 = {{T(), T(), T()}}; (void)a3_3; } // See http://wg21.link/LWG2157 std::array nodefault = {{}}; (void)nodefault; } } }; // Test construction from an initializer-list TEST_CONSTEXPR_CXX14 bool test_initializer_list() { { std::array const a3_0 = {}; assert(a3_0[0] == double()); assert(a3_0[1] == double()); assert(a3_0[2] == double()); } { std::array const a3_1 = {1}; assert(a3_1[0] == double(1)); assert(a3_1[1] == double()); assert(a3_1[2] == double()); } { std::array const a3_2 = {1, 2.2}; assert(a3_2[0] == double(1)); assert(a3_2[1] == 2.2); assert(a3_2[2] == double()); } { std::array const a3_3 = {1, 2, 3.5}; assert(a3_3[0] == double(1)); assert(a3_3[1] == double(2)); assert(a3_3[2] == 3.5); } return true; } struct Empty { }; struct Trivial { int i; int j; }; struct NonTrivial { TEST_CONSTEXPR NonTrivial() { } TEST_CONSTEXPR NonTrivial(NonTrivial const&) { } }; struct NonEmptyNonTrivial { int i; int j; TEST_CONSTEXPR NonEmptyNonTrivial() : i(22), j(33) { } TEST_CONSTEXPR NonEmptyNonTrivial(NonEmptyNonTrivial const&) : i(22), j(33) { } }; template TEST_CONSTEXPR_CXX14 bool with_all_types() { F().template operator()(); F().template operator()(); F().template operator()(); F().template operator()(); F().template operator()(); F().template operator()(); F().template operator()(); F().template operator()(); F().template operator()(); F().template operator()(); return true; } // This is a regression test -- previously, libc++ would implement empty arrays by // storing an array of characters, which means that the array would be initializable // from nonsense like an integer (or anything else that can be narrowed to char). #if TEST_STD_VER >= 20 template concept is_list_initializable_int = requires { { T{123} }; }; struct Foo { }; static_assert(!is_list_initializable_int>); static_assert(!is_list_initializable_int>); #endif int main(int, char**) { with_all_types(); test_initializer_list(); #if TEST_STD_VER >= 14 static_assert(with_all_types(), ""); static_assert(test_initializer_list(), ""); #endif return 0; }