
We've been improving these the tests for vector quite a bit and we are probably not done improving our container tests. Formatting everything at once will make subsequent reviews easier.
251 lines
6.3 KiB
C++
251 lines
6.3 KiB
C++
//===----------------------------------------------------------------------===//
|
|
//
|
|
// 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 <array>
|
|
#include <cassert>
|
|
#include <type_traits>
|
|
#include "test_macros.h"
|
|
|
|
struct NoDefault {
|
|
TEST_CONSTEXPR NoDefault(int) {}
|
|
};
|
|
|
|
struct test_initialization {
|
|
template <typename T>
|
|
TEST_CONSTEXPR_CXX14 void operator()() const {
|
|
// Check default initalization
|
|
{
|
|
std::array<T, 0> 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<T>::value))
|
|
#endif
|
|
{
|
|
std::array<T, 1> a1;
|
|
(void)a1;
|
|
std::array<T, 2> a2;
|
|
(void)a2;
|
|
std::array<T, 3> a3;
|
|
(void)a3;
|
|
}
|
|
|
|
std::array<NoDefault, 0> 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<T, 0> a0;
|
|
(void)a0;
|
|
const std::array<NoDefault, 0> nodefault;
|
|
(void)nodefault;
|
|
}
|
|
|
|
// Check direct-list-initialization syntax (introduced in C++11)
|
|
#if TEST_STD_VER >= 11
|
|
{
|
|
{
|
|
std::array<T, 0> a0_0{};
|
|
(void)a0_0;
|
|
}
|
|
{
|
|
std::array<T, 1> a1_0{};
|
|
(void)a1_0;
|
|
std::array<T, 1> a1_1{T()};
|
|
(void)a1_1;
|
|
}
|
|
{
|
|
std::array<T, 2> a2_0{};
|
|
(void)a2_0;
|
|
std::array<T, 2> a2_1{T()};
|
|
(void)a2_1;
|
|
std::array<T, 2> a2_2{T(), T()};
|
|
(void)a2_2;
|
|
}
|
|
{
|
|
std::array<T, 3> a3_0{};
|
|
(void)a3_0;
|
|
std::array<T, 3> a3_1{T()};
|
|
(void)a3_1;
|
|
std::array<T, 3> a3_2{T(), T()};
|
|
(void)a3_2;
|
|
std::array<T, 3> a3_3{T(), T(), T()};
|
|
(void)a3_3;
|
|
}
|
|
|
|
std::array<NoDefault, 0> nodefault{};
|
|
(void)nodefault;
|
|
}
|
|
#endif
|
|
|
|
// Check copy-list-initialization syntax
|
|
{
|
|
{
|
|
std::array<T, 0> a0_0 = {};
|
|
(void)a0_0;
|
|
}
|
|
{
|
|
std::array<T, 1> a1_0 = {};
|
|
(void)a1_0;
|
|
std::array<T, 1> a1_1 = {T()};
|
|
(void)a1_1;
|
|
}
|
|
{
|
|
std::array<T, 2> a2_0 = {};
|
|
(void)a2_0;
|
|
std::array<T, 2> a2_1 = {T()};
|
|
(void)a2_1;
|
|
std::array<T, 2> a2_2 = {T(), T()};
|
|
(void)a2_2;
|
|
}
|
|
{
|
|
std::array<T, 3> a3_0 = {};
|
|
(void)a3_0;
|
|
std::array<T, 3> a3_1 = {T()};
|
|
(void)a3_1;
|
|
std::array<T, 3> a3_2 = {T(), T()};
|
|
(void)a3_2;
|
|
std::array<T, 3> a3_3 = {T(), T(), T()};
|
|
(void)a3_3;
|
|
}
|
|
|
|
std::array<NoDefault, 0> nodefault = {};
|
|
(void)nodefault;
|
|
}
|
|
|
|
// Test aggregate initialization
|
|
{
|
|
{
|
|
std::array<T, 0> a0_0 = {{}};
|
|
(void)a0_0;
|
|
}
|
|
{
|
|
std::array<T, 1> a1_0 = {{}};
|
|
(void)a1_0;
|
|
std::array<T, 1> a1_1 = {{T()}};
|
|
(void)a1_1;
|
|
}
|
|
{
|
|
std::array<T, 2> a2_0 = {{}};
|
|
(void)a2_0;
|
|
std::array<T, 2> a2_1 = {{T()}};
|
|
(void)a2_1;
|
|
std::array<T, 2> a2_2 = {{T(), T()}};
|
|
(void)a2_2;
|
|
}
|
|
{
|
|
std::array<T, 3> a3_0 = {{}};
|
|
(void)a3_0;
|
|
std::array<T, 3> a3_1 = {{T()}};
|
|
(void)a3_1;
|
|
std::array<T, 3> a3_2 = {{T(), T()}};
|
|
(void)a3_2;
|
|
std::array<T, 3> a3_3 = {{T(), T(), T()}};
|
|
(void)a3_3;
|
|
}
|
|
|
|
// See http://wg21.link/LWG2157
|
|
std::array<NoDefault, 0> nodefault = {{}};
|
|
(void)nodefault;
|
|
}
|
|
}
|
|
};
|
|
|
|
// Test construction from an initializer-list
|
|
TEST_CONSTEXPR_CXX14 bool test_initializer_list() {
|
|
{
|
|
std::array<double, 3> const a3_0 = {};
|
|
assert(a3_0[0] == double());
|
|
assert(a3_0[1] == double());
|
|
assert(a3_0[2] == double());
|
|
}
|
|
{
|
|
std::array<double, 3> const a3_1 = {1};
|
|
assert(a3_1[0] == double(1));
|
|
assert(a3_1[1] == double());
|
|
assert(a3_1[2] == double());
|
|
}
|
|
{
|
|
std::array<double, 3> 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<double, 3> 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 <typename F>
|
|
TEST_CONSTEXPR_CXX14 bool with_all_types() {
|
|
F().template operator()<char>();
|
|
F().template operator()<int>();
|
|
F().template operator()<long>();
|
|
F().template operator()<float>();
|
|
F().template operator()<double>();
|
|
F().template operator()<long double>();
|
|
F().template operator()<Empty>();
|
|
F().template operator()<Trivial>();
|
|
F().template operator()<NonTrivial>();
|
|
F().template operator()<NonEmptyNonTrivial>();
|
|
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 <class T>
|
|
concept is_list_initializable_int = requires {
|
|
{ T{123} };
|
|
};
|
|
|
|
struct Foo {};
|
|
static_assert(!is_list_initializable_int<std::array<Foo, 0>>);
|
|
static_assert(!is_list_initializable_int<std::array<Foo, 1>>);
|
|
#endif
|
|
|
|
int main(int, char**) {
|
|
with_all_types<test_initialization>();
|
|
test_initializer_list();
|
|
#if TEST_STD_VER >= 14
|
|
static_assert(with_all_types<test_initialization>(), "");
|
|
static_assert(test_initializer_list(), "");
|
|
#endif
|
|
|
|
return 0;
|
|
}
|