[libc++] Complete overhaul of constexpr support in std::array

This commit adds missing support for constexpr in std::array under all
standard modes up to and including C++20. It also transforms the <array>
tests to check for constexpr-friendliness under the right standard modes.

Fixes https://llvm.org/PR40124
Fixes rdar://57522096
Supersedes https://reviews.llvm.org/D60666

Differential Revision: https://reviews.llvm.org/D80452
This commit is contained in:
Louis Dionne
2020-05-22 09:59:48 -04:00
parent b726d071b4
commit 77b9abfc8e
38 changed files with 1196 additions and 825 deletions

View File

@@ -168,6 +168,8 @@ Status
------------------------------------------------- -----------------
**C++ 2a**
-------------------------------------------------------------------
``__cpp_lib_array_constexpr`` ``201811L``
------------------------------------------------- -----------------
``__cpp_lib_atomic_ref`` *unimplemented*
------------------------------------------------- -----------------
``__cpp_lib_bind_front`` *unimplemented*

View File

@@ -32,24 +32,24 @@ struct array
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
// No explicit construct/copy/destroy for aggregate type
void fill(const T& u);
void swap(array& a) noexcept(is_nothrow_swappable_v<T>);
void fill(const T& u); // constexpr in C++20
void swap(array& a) noexcept(is_nothrow_swappable_v<T>); // constexpr in C++20
// iterators:
iterator begin() noexcept;
const_iterator begin() const noexcept;
iterator end() noexcept;
const_iterator end() const noexcept;
iterator begin() noexcept; // constexpr in C++17
const_iterator begin() const noexcept; // constexpr in C++17
iterator end() noexcept; // constexpr in C++17
const_iterator end() const noexcept; // constexpr in C++17
reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;
reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;
reverse_iterator rbegin() noexcept; // constexpr in C++17
const_reverse_iterator rbegin() const noexcept; // constexpr in C++17
reverse_iterator rend() noexcept; // constexpr in C++17
const_reverse_iterator rend() const noexcept; // constexpr in C++17
const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
const_iterator cbegin() const noexcept; // constexpr in C++17
const_iterator cend() const noexcept; // constexpr in C++17
const_reverse_iterator crbegin() const noexcept; // constexpr in C++17
const_reverse_iterator crend() const noexcept; // constexpr in C++17
// capacity:
constexpr size_type size() const noexcept;
@@ -57,46 +57,51 @@ struct array
constexpr bool empty() const noexcept;
// element access:
reference operator[](size_type n);
const_reference operator[](size_type n) const; // constexpr in C++14
const_reference at(size_type n) const; // constexpr in C++14
reference at(size_type n);
reference operator[](size_type n); // constexpr in C++17
const_reference operator[](size_type n) const; // constexpr in C++14
reference at(size_type n); // constexpr in C++17
const_reference at(size_type n) const; // constexpr in C++14
reference front();
const_reference front() const; // constexpr in C++14
reference back();
const_reference back() const; // constexpr in C++14
reference front(); // constexpr in C++17
const_reference front() const; // constexpr in C++14
reference back(); // constexpr in C++17
const_reference back() const; // constexpr in C++14
T* data() noexcept;
const T* data() const noexcept;
T* data() noexcept; // constexpr in C++17
const T* data() const noexcept; // constexpr in C++17
};
template <class T, class... U>
array(T, U...) -> array<T, 1 + sizeof...(U)>;
template <class T, class... U>
array(T, U...) -> array<T, 1 + sizeof...(U)>; // C++17
template <class T, size_t N>
bool operator==(const array<T,N>& x, const array<T,N>& y);
bool operator==(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20
template <class T, size_t N>
bool operator!=(const array<T,N>& x, const array<T,N>& y);
bool operator!=(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20
template <class T, size_t N>
bool operator<(const array<T,N>& x, const array<T,N>& y);
bool operator<(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20
template <class T, size_t N>
bool operator>(const array<T,N>& x, const array<T,N>& y);
bool operator>(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20
template <class T, size_t N>
bool operator<=(const array<T,N>& x, const array<T,N>& y);
bool operator<=(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20
template <class T, size_t N>
bool operator>=(const array<T,N>& x, const array<T,N>& y);
bool operator>=(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20
template <class T, size_t N >
void swap(array<T,N>& x, array<T,N>& y) noexcept(noexcept(x.swap(y))); // C++17
void swap(array<T,N>& x, array<T,N>& y) noexcept(noexcept(x.swap(y))); // constexpr in C++20
template <class T, size_t N>
constexpr array<remove_cv_t<T>, N> to_array(T (&a)[N]); // C++20
template <class T, size_t N>
constexpr array<remove_cv_t<T>, N> to_array(T (&&a)[N]); // C++20
template <class T> struct tuple_size;
template <size_t I, class T> struct tuple_element;
template <class T, size_t N> struct tuple_size<array<T, N>>;
template <size_t I, class T, size_t N> struct tuple_element<I, array<T, N>>;
template <size_t I, class T, size_t N> T& get(array<T, N>&) noexcept; // constexpr in C++14
template <size_t I, class T, size_t N> const T& get(const array<T, N>&) noexcept; // constexpr in C++14
template <size_t I, class T, size_t N> T&& get(array<T, N>&&) noexcept; // constexpr in C++14
template <size_t I, class T, size_t N> T& get(array<T, N>&) noexcept; // constexpr in C++14
template <size_t I, class T, size_t N> const T& get(const array<T, N>&) noexcept; // constexpr in C++14
template <size_t I, class T, size_t N> T&& get(array<T, N>&&) noexcept; // constexpr in C++14
template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexcept; // constexpr in C++14
} // std
@@ -143,11 +148,12 @@ struct _LIBCPP_TEMPLATE_VIS array
_Tp __elems_[_Size];
// No explicit construct/copy/destroy for aggregate type
_LIBCPP_INLINE_VISIBILITY void fill(const value_type& __u) {
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
void fill(const value_type& __u) {
_VSTD::fill_n(__elems_, _Size, __u);
}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
void swap(array& __a) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value) {
std::swap_ranges(__elems_, __elems_ + _Size, __a.__elems_);
}
@@ -236,50 +242,71 @@ struct _LIBCPP_TEMPLATE_VIS array<_Tp, 0>
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
#ifndef _LIBCPP_CXX03_LANG
union __wrapper {
_LIBCPP_CONSTEXPR __wrapper() : __b() { }
~__wrapper() = default;
bool __b;
_Tp __t;
} __w;
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
value_type* data() _NOEXCEPT {return &__w.__t;}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
const value_type* data() const _NOEXCEPT {return &__w.__t;}
#else // C++03
typedef typename conditional<is_const<_Tp>::value, const char,
char>::type _CharType;
struct _ArrayInStructT { _Tp __data_[1]; };
_ALIGNAS_TYPE(_ArrayInStructT) _CharType __elems_[sizeof(_ArrayInStructT)];
_LIBCPP_INLINE_VISIBILITY
value_type* data() _NOEXCEPT {return reinterpret_cast<value_type*>(__elems_);}
_LIBCPP_INLINE_VISIBILITY
const value_type* data() const _NOEXCEPT {return reinterpret_cast<const value_type*>(__elems_);}
#endif
// No explicit construct/copy/destroy for aggregate type
_LIBCPP_INLINE_VISIBILITY void fill(const value_type&) {
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
void fill(const value_type&) {
static_assert(!is_const<_Tp>::value,
"cannot fill zero-sized array of type 'const T'");
}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
void swap(array&) _NOEXCEPT {
static_assert(!is_const<_Tp>::value,
"cannot swap zero-sized array of type 'const T'");
}
// iterators:
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
iterator begin() _NOEXCEPT {return iterator(data());}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
const_iterator begin() const _NOEXCEPT {return const_iterator(data());}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
iterator end() _NOEXCEPT {return iterator(data());}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
const_iterator end() const _NOEXCEPT {return const_iterator(data());}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
const_iterator cbegin() const _NOEXCEPT {return begin();}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
const_iterator cend() const _NOEXCEPT {return end();}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
const_reverse_iterator crend() const _NOEXCEPT {return rend();}
// capacity:
@@ -291,7 +318,7 @@ struct _LIBCPP_TEMPLATE_VIS array<_Tp, 0>
_LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT {return true;}
// element access:
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
reference operator[](size_type) _NOEXCEPT {
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::operator[] on a zero-sized array");
_LIBCPP_UNREACHABLE();
@@ -303,46 +330,41 @@ struct _LIBCPP_TEMPLATE_VIS array<_Tp, 0>
_LIBCPP_UNREACHABLE();
}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
reference at(size_type) {
__throw_out_of_range("array<T, 0>::at");
_LIBCPP_UNREACHABLE();
}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
const_reference at(size_type) const {
__throw_out_of_range("array<T, 0>::at");
_LIBCPP_UNREACHABLE();
}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
reference front() _NOEXCEPT {
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::front() on a zero-sized array");
_LIBCPP_UNREACHABLE();
}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
const_reference front() const _NOEXCEPT {
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::front() on a zero-sized array");
_LIBCPP_UNREACHABLE();
}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
reference back() _NOEXCEPT {
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::back() on a zero-sized array");
_LIBCPP_UNREACHABLE();
}
_LIBCPP_INLINE_VISIBILITY
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
const_reference back() const _NOEXCEPT {
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::back() on a zero-sized array");
_LIBCPP_UNREACHABLE();
}
_LIBCPP_INLINE_VISIBILITY
value_type* data() _NOEXCEPT {return reinterpret_cast<value_type*>(__elems_);}
_LIBCPP_INLINE_VISIBILITY
const value_type* data() const _NOEXCEPT {return reinterpret_cast<const value_type*>(__elems_);}
};
@@ -404,7 +426,7 @@ operator>=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
}
template <class _Tp, size_t _Size>
inline _LIBCPP_INLINE_VISIBILITY
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
typename enable_if
<
_Size == 0 ||

View File

@@ -21,7 +21,8 @@ __cpp_lib_allocator_traits_is_always_equal 201411L <memory> <scoped
<unordered_map> <unordered_set>
__cpp_lib_any 201606L <any>
__cpp_lib_apply 201603L <tuple>
__cpp_lib_array_constexpr 201603L <iterator> <array>
__cpp_lib_array_constexpr 201811L <iterator> <array>
201603L // C++17
__cpp_lib_as_const 201510L <utility>
__cpp_lib_atomic_is_always_lock_free 201603L <atomic>
__cpp_lib_atomic_ref 201806L <atomic>
@@ -212,6 +213,8 @@ __cpp_lib_void_t 201411L <type_traits>
#endif
#if _LIBCPP_STD_VER > 17
# undef __cpp_lib_array_constexpr
# define __cpp_lib_array_constexpr 201811L
# if !defined(_LIBCPP_HAS_NO_THREADS)
// # define __cpp_lib_atomic_ref 201806L
# endif

View File

@@ -0,0 +1,50 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// Make sure std::array is an aggregate type.
#include <array>
#include <type_traits>
template <typename T>
void tests()
{
// Test aggregate initialization
{
std::array<T, 0> a0 = {}; (void)a0;
std::array<T, 1> a1 = {T()}; (void)a1;
std::array<T, 2> a2 = {T(), T()}; (void)a2;
std::array<T, 3> a3 = {T(), T(), T()}; (void)a3;
}
// Test the is_aggregate trait.
#if TEST_STD_VER >= 17 // The trait is only available in C++17 and above
static_assert(std::is_aggregate<std::array<T, 0> >::value, "");
static_assert(std::is_aggregate<std::array<T, 1> >::value, "");
static_assert(std::is_aggregate<std::array<T, 2> >::value, "");
static_assert(std::is_aggregate<std::array<T, 3> >::value, "");
static_assert(std::is_aggregate<std::array<T, 4> >::value, "");
#endif
}
struct Empty { };
struct NonEmpty { int i; int j; };
int main(int, char**)
{
tests<char>();
tests<int>();
tests<long>();
tests<float>();
tests<double>();
tests<long double>();
tests<NonEmpty>();
tests<Empty>();
return 0;
}

View File

@@ -30,37 +30,44 @@
#include "test_macros.h"
constexpr bool tests()
{
// Test the explicit deduction guides
{
std::array arr{1,2,3}; // array(T, U...)
static_assert(std::is_same_v<decltype(arr), std::array<int, 3>>, "");
assert(arr[0] == 1);
assert(arr[1] == 2);
assert(arr[2] == 3);
}
{
const long l1 = 42;
std::array arr{1L, 4L, 9L, l1}; // array(T, U...)
static_assert(std::is_same_v<decltype(arr)::value_type, long>, "");
static_assert(arr.size() == 4, "");
assert(arr[0] == 1);
assert(arr[1] == 4);
assert(arr[2] == 9);
assert(arr[3] == l1);
}
// Test the implicit deduction guides
{
std::array<double, 2> source = {4.0, 5.0};
std::array arr(source); // array(array)
static_assert(std::is_same_v<decltype(arr), decltype(source)>, "");
static_assert(std::is_same_v<decltype(arr), std::array<double, 2>>, "");
assert(arr[0] == 4.0);
assert(arr[1] == 5.0);
}
return true;
}
int main(int, char**)
{
// Test the explicit deduction guides
{
std::array arr{1,2,3}; // array(T, U...)
static_assert(std::is_same_v<decltype(arr), std::array<int, 3>>, "");
assert(arr[0] == 1);
assert(arr[1] == 2);
assert(arr[2] == 3);
}
{
const long l1 = 42;
std::array arr{1L, 4L, 9L, l1}; // array(T, U...)
static_assert(std::is_same_v<decltype(arr)::value_type, long>, "");
static_assert(arr.size() == 4, "");
assert(arr[0] == 1);
assert(arr[1] == 4);
assert(arr[2] == 9);
assert(arr[3] == l1);
}
// Test the implicit deduction guides
{
std::array<double, 2> source = {4.0, 5.0};
std::array arr(source); // array(array)
static_assert(std::is_same_v<decltype(arr), decltype(source)>, "");
static_assert(std::is_same_v<decltype(arr), std::array<double, 2>>, "");
assert(arr[0] == 4.0);
assert(arr[1] == 5.0);
}
return 0;
tests();
static_assert(tests(), "");
return 0;
}

View File

@@ -19,32 +19,43 @@
#include "disable_missing_braces_warning.h"
struct NoDefault {
NoDefault(int) {}
TEST_CONSTEXPR NoDefault(int) { }
};
struct Default {
TEST_CONSTEXPR Default() { }
};
TEST_CONSTEXPR_CXX14 bool tests()
{
{
std::array<Default, 3> array;
assert(array.size() == 3);
}
{
std::array<Default, 0> array;
assert(array.size() == 0);
}
{
typedef std::array<NoDefault, 0> C;
C c;
assert(c.size() == 0);
C c1 = {};
assert(c1.size() == 0);
C c2 = {{}};
assert(c2.size() == 0);
}
return true;
}
int main(int, char**)
{
{
typedef double T;
typedef std::array<T, 3> C;
C c;
assert(c.size() == 3);
}
{
typedef double T;
typedef std::array<T, 0> C;
C c;
assert(c.size() == 0);
}
{
typedef std::array<NoDefault, 0> C;
C c;
assert(c.size() == 0);
C c1 = {};
assert(c1.size() == 0);
C c2 = {{}};
assert(c2.size() == 0);
}
return 0;
tests();
#if TEST_STD_VER >= 14
static_assert(tests(), "");
#endif
return 0;
}

View File

@@ -23,72 +23,81 @@
// generated operator would be ill-formed; like in the case of a struct with a
// const member.
#if TEST_STD_VER < 11
#define TEST_NOT_COPY_ASSIGNABLE(T) ((void)0)
# define TEST_NOT_COPY_ASSIGNABLE(T) ((void)0)
#else
#define TEST_NOT_COPY_ASSIGNABLE(T) static_assert(!std::is_copy_assignable<T>::value, "")
# define TEST_NOT_COPY_ASSIGNABLE(T) static_assert(!std::is_copy_assignable<T>::value, "")
#endif
struct NoDefault {
NoDefault(int) {}
TEST_CONSTEXPR NoDefault(int) { }
};
int main(int, char**) {
{
typedef double T;
typedef std::array<T, 3> C;
C c = {1.1, 2.2, 3.3};
C c2 = c;
c2 = c;
static_assert(std::is_copy_constructible<C>::value, "");
static_assert(std::is_copy_assignable<C>::value, "");
}
{
typedef double T;
typedef std::array<const T, 3> C;
C c = {1.1, 2.2, 3.3};
C c2 = c;
((void)c2);
static_assert(std::is_copy_constructible<C>::value, "");
TEST_NOT_COPY_ASSIGNABLE(C);
}
{
typedef double T;
typedef std::array<T, 0> C;
C c = {};
C c2 = c;
c2 = c;
static_assert(std::is_copy_constructible<C>::value, "");
static_assert(std::is_copy_assignable<C>::value, "");
}
{
// const arrays of size 0 should disable the implicit copy assignment operator.
typedef double T;
typedef std::array<const T, 0> C;
C c = {{}};
C c2 = c;
((void)c2);
static_assert(std::is_copy_constructible<C>::value, "");
TEST_NOT_COPY_ASSIGNABLE(C);
}
{
typedef NoDefault T;
typedef std::array<T, 0> C;
C c = {};
C c2 = c;
c2 = c;
static_assert(std::is_copy_constructible<C>::value, "");
static_assert(std::is_copy_assignable<C>::value, "");
}
{
typedef NoDefault T;
typedef std::array<const T, 0> C;
C c = {{}};
C c2 = c;
((void)c2);
static_assert(std::is_copy_constructible<C>::value, "");
TEST_NOT_COPY_ASSIGNABLE(C);
}
TEST_CONSTEXPR_CXX14 bool tests()
{
{
typedef double T;
typedef std::array<T, 3> C;
C c = {1.1, 2.2, 3.3};
C c2 = c;
c2 = c;
static_assert(std::is_copy_constructible<C>::value, "");
static_assert(std::is_copy_assignable<C>::value, "");
}
{
typedef double T;
typedef std::array<const T, 3> C;
C c = {1.1, 2.2, 3.3};
C c2 = c;
((void)c2);
static_assert(std::is_copy_constructible<C>::value, "");
TEST_NOT_COPY_ASSIGNABLE(C);
}
{
typedef double T;
typedef std::array<T, 0> C;
C c = {};
C c2 = c;
c2 = c;
static_assert(std::is_copy_constructible<C>::value, "");
static_assert(std::is_copy_assignable<C>::value, "");
}
{
// const arrays of size 0 should disable the implicit copy assignment operator.
typedef double T;
typedef std::array<const T, 0> C;
C c = {{}};
C c2 = c;
((void)c2);
static_assert(std::is_copy_constructible<C>::value, "");
TEST_NOT_COPY_ASSIGNABLE(C);
}
{
typedef NoDefault T;
typedef std::array<T, 0> C;
C c = {};
C c2 = c;
c2 = c;
static_assert(std::is_copy_constructible<C>::value, "");
static_assert(std::is_copy_assignable<C>::value, "");
}
{
typedef NoDefault T;
typedef std::array<const T, 0> C;
C c = {{}};
C c2 = c;
((void)c2);
static_assert(std::is_copy_constructible<C>::value, "");
TEST_NOT_COPY_ASSIGNABLE(C);
}
return 0;
return true;
}
int main(int, char**)
{
tests();
#if TEST_STD_VER >= 14
static_assert(tests(), "");
#endif
return 0;
}

View File

@@ -18,12 +18,12 @@
#include "test_macros.h"
#include "disable_missing_braces_warning.h"
int main(int, char**)
TEST_CONSTEXPR_CXX14 bool tests()
{
{
typedef double T;
typedef std::array<T, 3> C;
C c = {1, 2, 3.5};
C const c = {1, 2, 3.5};
assert(c.size() == 3);
assert(c[0] == 1);
assert(c[1] == 2);
@@ -32,23 +32,32 @@ int main(int, char**)
{
typedef double T;
typedef std::array<T, 0> C;
C c = {};
C const c = {};
assert(c.size() == 0);
}
{
typedef double T;
typedef std::array<T, 3> C;
C c = {1};
C const c = {1};
assert(c.size() == 3.0);
assert(c[0] == 1);
}
{
typedef int T;
typedef std::array<T, 1> C;
C c = {};
C const c = {};
assert(c.size() == 1);
}
return 0;
return true;
}
int main(int, char**)
{
tests();
#if TEST_STD_VER >= 14
static_assert(tests(), "");
#endif
return 0;
}

View File

@@ -23,7 +23,8 @@
#include "test_macros.h"
#include "MoveOnly.h"
int main(int, char**) {
constexpr bool tests()
{
// Test deduced type.
{
auto arr = std::to_array({1, 2, 3});
@@ -110,13 +111,12 @@ int main(int, char**) {
assert(arr[0].b == .1);
}
// Test constexpr.
{
constexpr std::array<int, 3> arr = std::to_array({1, 2, 3});
static_assert(arr[0] == 1);
static_assert(arr[1] == 2);
static_assert(arr[2] == 3);
}
return true;
}
int main(int, char**)
{
tests();
static_assert(tests(), "");
return 0;
}

View File

@@ -21,7 +21,7 @@
#include "disable_missing_braces_warning.h"
struct NoDefault {
NoDefault(int) {}
TEST_CONSTEXPR NoDefault(int) { }
};
#if TEST_STD_VER < 11
@@ -33,7 +33,7 @@ struct natural_alignment {
};
#endif
int main(int, char**)
TEST_CONSTEXPR_CXX17 bool tests()
{
{
typedef double T;
@@ -52,33 +52,49 @@ int main(int, char**)
LIBCPP_ASSERT(p != nullptr);
}
{
typedef double T;
typedef std::array<const T, 0> C;
C c = {{}};
const T* p = c.data();
static_assert((std::is_same<decltype(c.data()), const T*>::value), "");
LIBCPP_ASSERT(p != nullptr);
}
{
#if TEST_STD_VER < 11
typedef natural_alignment T;
#else
typedef std::max_align_t T;
#endif
typedef std::array<T, 0> C;
const C c = {};
const T* p = c.data();
LIBCPP_ASSERT(p != nullptr);
std::uintptr_t pint = reinterpret_cast<std::uintptr_t>(p);
assert(pint % TEST_ALIGNOF(T) == 0);
typedef double T;
typedef std::array<const T, 0> C;
C c = {{}};
const T* p = c.data();
LIBCPP_ASSERT(p != nullptr);
static_assert((std::is_same<decltype(c.data()), const T*>::value), "");
}
{
typedef NoDefault T;
typedef std::array<T, 0> C;
C c = {};
T* p = c.data();
LIBCPP_ASSERT(p != nullptr);
typedef NoDefault T;
typedef std::array<T, 0> C;
C c = {};
T* p = c.data();
LIBCPP_ASSERT(p != nullptr);
}
{
std::array<int, 5> c = {0, 1, 2, 3, 4};
assert(c.data() == &c[0]);
assert(*c.data() == c[0]);
}
return 0;
return true;
}
int main(int, char**)
{
tests();
#if TEST_STD_VER >= 17
static_assert(tests(), "");
#endif
// Test the alignment of data()
{
#if TEST_STD_VER < 11
typedef natural_alignment T;
#else
typedef std::max_align_t T;
#endif
typedef std::array<T, 0> C;
const C c = {};
const T* p = c.data();
LIBCPP_ASSERT(p != nullptr);
std::uintptr_t pint = reinterpret_cast<std::uintptr_t>(p);
assert(pint % TEST_ALIGNOF(T) == 0);
}
return 0;
}

View File

@@ -21,7 +21,7 @@
#include "disable_missing_braces_warning.h"
struct NoDefault {
NoDefault(int) {}
TEST_CONSTEXPR NoDefault(int) { }
};
#if TEST_STD_VER < 11
@@ -33,7 +33,7 @@ struct natural_alignment {
};
#endif
int main(int, char**)
TEST_CONSTEXPR_CXX17 bool tests()
{
{
typedef double T;
@@ -49,40 +49,45 @@ int main(int, char**)
typedef std::array<T, 0> C;
const C c = {};
const T* p = c.data();
(void)p; // to placate scan-build
LIBCPP_ASSERT(p != nullptr);
}
{
typedef NoDefault T;
typedef std::array<T, 0> C;
const C c = {};
const T* p = c.data();
LIBCPP_ASSERT(p != nullptr);
typedef NoDefault T;
typedef std::array<T, 0> C;
const C c = {};
const T* p = c.data();
LIBCPP_ASSERT(p != nullptr);
}
{
std::array<int, 5> const c = {0, 1, 2, 3, 4};
assert(c.data() == &c[0]);
assert(*c.data() == c[0]);
}
return true;
}
int main(int, char**)
{
tests();
#if TEST_STD_VER >= 17
static_assert(tests(), "");
#endif
// Test the alignment of data()
{
#if TEST_STD_VER < 11
typedef natural_alignment T;
typedef natural_alignment T;
#else
typedef std::max_align_t T;
typedef std::max_align_t T;
#endif
typedef std::array<T, 0> C;
const C c = {};
const T* p = c.data();
LIBCPP_ASSERT(p != nullptr);
std::uintptr_t pint = reinterpret_cast<std::uintptr_t>(p);
assert(pint % TEST_ALIGNOF(T) == 0);
typedef std::array<T, 0> C;
const C c = {};
const T* p = c.data();
LIBCPP_ASSERT(p != nullptr);
std::uintptr_t pint = reinterpret_cast<std::uintptr_t>(p);
assert(pint % TEST_ALIGNOF(T) == 0);
}
#if TEST_STD_VER > 14
{
typedef std::array<int, 5> C;
constexpr C c1{0,1,2,3,4};
constexpr const C c2{0,1,2,3,4};
static_assert ( c1.data() == &c1[0], "");
static_assert ( *c1.data() == c1[0], "");
static_assert ( c2.data() == &c2[0], "");
static_assert ( *c2.data() == c2[0], "");
}
#endif
return 0;
return 0;
}

View File

@@ -18,7 +18,7 @@
#include "test_macros.h"
#include "disable_missing_braces_warning.h"
int main(int, char**)
TEST_CONSTEXPR_CXX20 bool tests()
{
{
typedef double T;
@@ -30,6 +30,7 @@ int main(int, char**)
assert(c[1] == 5.5);
assert(c[2] == 5.5);
}
{
typedef double T;
typedef std::array<T, 0> C;
@@ -37,6 +38,14 @@ int main(int, char**)
c.fill(5.5);
assert(c.size() == 0);
}
return 0;
return true;
}
int main(int, char**)
{
tests();
#if TEST_STD_VER >= 20
static_assert(tests(), "");
#endif
return 0;
}

View File

@@ -56,5 +56,5 @@ int main(int, char**)
}
#endif
return 0;
return 0;
}

View File

@@ -19,10 +19,10 @@
#include "disable_missing_braces_warning.h"
struct NonSwappable {
NonSwappable() {}
TEST_CONSTEXPR NonSwappable() { }
private:
NonSwappable(NonSwappable const&);
NonSwappable& operator=(NonSwappable const&);
NonSwappable(NonSwappable const&);
NonSwappable& operator=(NonSwappable const&);
};
template <class Tp>
@@ -33,9 +33,9 @@ template <class Tp>
std::false_type can_swap_imp(...);
template <class Tp>
struct can_swap : std::is_same<decltype(can_swap_imp<Tp>(0)), void> {};
struct can_swap : std::is_same<decltype(can_swap_imp<Tp>(0)), void> { };
int main(int, char**)
TEST_CONSTEXPR_CXX20 bool tests()
{
{
typedef double T;
@@ -82,5 +82,14 @@ int main(int, char**)
}
#endif
return 0;
return true;
}
int main(int, char**)
{
tests();
#if TEST_STD_VER >= 20
static_assert(tests(), "");
#endif
return 0;
}

View File

@@ -21,13 +21,13 @@
#include "disable_missing_braces_warning.h"
struct NonSwappable {
NonSwappable() {}
TEST_CONSTEXPR NonSwappable() { }
private:
NonSwappable(NonSwappable const&);
NonSwappable& operator=(NonSwappable const&);
NonSwappable(NonSwappable const&);
NonSwappable& operator=(NonSwappable const&);
};
int main(int, char**)
TEST_CONSTEXPR_CXX20 bool tests()
{
{
typedef double T;
@@ -89,6 +89,14 @@ int main(int, char**)
#endif
}
return true;
}
int main(int, char**)
{
tests();
#if TEST_STD_VER >= 20
static_assert(tests(), "");
#endif
return 0;
}

View File

@@ -20,41 +20,57 @@
#include "disable_missing_braces_warning.h"
#if TEST_STD_VER > 11
struct S {
std::array<int, 3> a;
int k;
constexpr S() : a{1,2,3}, k(std::get<2>(a)) {}
};
template <typename ...T>
TEST_CONSTEXPR std::array<int, sizeof...(T)> tempArray(T ...args)
{
return {args...};
}
constexpr std::array<int, 2> getArr () { return { 3, 4 }; }
#endif
TEST_CONSTEXPR_CXX14 bool tests()
{
{
std::array<double, 1> array = {3.3};
assert(std::get<0>(array) == 3.3);
std::get<0>(array) = 99.1;
assert(std::get<0>(array) == 99.1);
}
{
std::array<double, 2> array = {3.3, 4.4};
assert(std::get<0>(array) == 3.3);
assert(std::get<1>(array) == 4.4);
std::get<0>(array) = 99.1;
std::get<1>(array) = 99.2;
assert(std::get<0>(array) == 99.1);
assert(std::get<1>(array) == 99.2);
}
{
std::array<double, 3> array = {3.3, 4.4, 5.5};
assert(std::get<0>(array) == 3.3);
assert(std::get<1>(array) == 4.4);
assert(std::get<2>(array) == 5.5);
std::get<1>(array) = 99.2;
assert(std::get<0>(array) == 3.3);
assert(std::get<1>(array) == 99.2);
assert(std::get<2>(array) == 5.5);
}
{
std::array<double, 1> array = {3.3};
static_assert(std::is_same<double&, decltype(std::get<0>(array))>::value, "");
}
{
assert(std::get<0>(tempArray(1, 2, 3)) == 1);
assert(std::get<1>(tempArray(1, 2, 3)) == 2);
assert(std::get<2>(tempArray(1, 2, 3)) == 3);
}
return true;
}
int main(int, char**)
{
{
typedef double T;
typedef std::array<T, 3> C;
C c = {1, 2, 3.5};
std::get<1>(c) = 5.5;
assert(c[0] == 1);
assert(c[1] == 5.5);
assert(c[2] == 3.5);
}
#if TEST_STD_VER > 11
{
typedef double T;
typedef std::array<T, 3> C;
constexpr C c = {1, 2, 3.5};
static_assert(std::get<0>(c) == 1, "");
static_assert(std::get<1>(c) == 2, "");
static_assert(std::get<2>(c) == 3.5, "");
}
{
static_assert(S().k == 3, "");
static_assert(std::get<1>(getArr()) == 4, "");
}
tests();
#if TEST_STD_VER >= 14
static_assert(tests(), "");
#endif
return 0;
return 0;
}

View File

@@ -19,26 +19,36 @@
// Disable the missing braces warning for this reason.
#include "disable_missing_braces_warning.h"
int main(int, char**)
TEST_CONSTEXPR_CXX14 bool tests()
{
{
typedef double T;
typedef std::array<T, 3> C;
const C c = {1, 2, 3.5};
assert(std::get<0>(c) == 1);
assert(std::get<1>(c) == 2);
assert(std::get<2>(c) == 3.5);
std::array<double, 1> const array = {3.3};
assert(std::get<0>(array) == 3.3);
}
#if TEST_STD_VER > 11
{
typedef double T;
typedef std::array<T, 3> C;
constexpr const C c = {1, 2, 3.5};
static_assert(std::get<0>(c) == 1, "");
static_assert(std::get<1>(c) == 2, "");
static_assert(std::get<2>(c) == 3.5, "");
std::array<double, 2> const array = {3.3, 4.4};
assert(std::get<0>(array) == 3.3);
assert(std::get<1>(array) == 4.4);
}
{
std::array<double, 3> const array = {3.3, 4.4, 5.5};
assert(std::get<0>(array) == 3.3);
assert(std::get<1>(array) == 4.4);
assert(std::get<2>(array) == 5.5);
}
{
std::array<double, 1> const array = {3.3};
static_assert(std::is_same<double const&, decltype(std::get<0>(array))>::value, "");
}
#endif
return 0;
return true;
}
int main(int, char**)
{
tests();
#if TEST_STD_VER >= 14
static_assert(tests(), "");
#endif
return 0;
}

View File

@@ -28,25 +28,25 @@ int main(int, char**)
{
{
typedef std::unique_ptr<double> T;
typedef std::array<T, 1> C;
const C c = {std::unique_ptr<double>(new double(3.5))};
static_assert(std::is_same<const T&&, decltype(std::get<0>(std::move(c)))>::value, "");
static_assert(noexcept(std::get<0>(std::move(c))), "");
const T&& t = std::get<0>(std::move(c));
assert(*t == 3.5);
typedef std::unique_ptr<double> T;
typedef std::array<T, 1> C;
const C c = {std::unique_ptr<double>(new double(3.5))};
static_assert(std::is_same<const T&&, decltype(std::get<0>(std::move(c)))>::value, "");
static_assert(noexcept(std::get<0>(std::move(c))), "");
const T&& t = std::get<0>(std::move(c));
assert(*t == 3.5);
}
#if TEST_STD_VER > 11
#if TEST_STD_VER >= 14
{
typedef double T;
typedef std::array<T, 3> C;
constexpr const C c = {1, 2, 3.5};
static_assert(std::get<0>(std::move(c)) == 1, "");
static_assert(std::get<1>(std::move(c)) == 2, "");
static_assert(std::get<2>(std::move(c)) == 3.5, "");
typedef double T;
typedef std::array<T, 3> C;
constexpr const C c = {1, 2, 3.5};
static_assert(std::get<0>(std::move(c)) == 1, "");
static_assert(std::get<1>(std::move(c)) == 2, "");
static_assert(std::get<2>(std::move(c)) == 3.5, "");
}
#endif
return 0;
return 0;
}

View File

@@ -33,5 +33,5 @@ int main(int, char**)
assert(*t == 3.5);
}
return 0;
return 0;
}

View File

@@ -18,7 +18,6 @@
#include <array>
#include <cassert>
// std::array is explicitly allowed to be initialized with A a = { init-list };.
// Disable the missing braces warning for this reason.
#include "disable_missing_braces_warning.h"

View File

@@ -8,10 +8,7 @@
// <array>
// reference operator[] (size_type)
// const_reference operator[] (size_type); // constexpr in C++14
// reference at (size_type)
// const_reference at (size_type); // constexpr in C++14
// reference at (size_type); // constexpr in C++17
#include <array>
#include <cassert>
@@ -26,100 +23,91 @@
// Disable the missing braces warning for this reason.
#include "disable_missing_braces_warning.h"
#if TEST_STD_VER > 14
constexpr bool check_idx( size_t idx, double val )
{
std::array<double, 3> arr = {1, 2, 3.5};
return arr.at(idx) == val;
}
#endif
int main(int, char**)
TEST_CONSTEXPR_CXX17 bool tests()
{
{
typedef double T;
typedef std::array<T, 3> C;
C c = {1, 2, 3.5};
C::reference r1 = c.at(0);
typename C::reference r1 = c.at(0);
assert(r1 == 1);
r1 = 5.5;
assert(c.front() == 5.5);
assert(c[0] == 5.5);
C::reference r2 = c.at(2);
typename C::reference r2 = c.at(2);
assert(r2 == 3.5);
r2 = 7.5;
assert(c.back() == 7.5);
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
TEST_IGNORE_NODISCARD c.at(3);
assert(false);
}
catch (const std::out_of_range &) {}
#endif
assert(c[2] == 7.5);
}
#ifndef TEST_HAS_NO_EXCEPTIONS
{
typedef double T;
typedef std::array<T, 0> C;
C c = {};
C const& cc = c;
try
{
TEST_IGNORE_NODISCARD c.at(0);
assert(false);
}
catch (const std::out_of_range &) {}
try
{
TEST_IGNORE_NODISCARD cc.at(0);
assert(false);
}
catch (const std::out_of_range &) {}
}
#endif
{
typedef double T;
typedef std::array<T, 3> C;
const C c = {1, 2, 3.5};
C::const_reference r1 = c.at(0);
assert(r1 == 1);
C::const_reference r2 = c.at(2);
assert(r2 == 3.5);
#ifndef TEST_HAS_NO_EXCEPTIONS
try
{
TEST_IGNORE_NODISCARD c.at(3);
assert(false);
}
catch (const std::out_of_range &) {}
#endif
}
#if TEST_STD_VER > 11
{
typedef double T;
typedef std::array<T, 3> C;
constexpr C c = {1, 2, 3.5};
constexpr T t1 = c.at(0);
static_assert (t1 == 1, "");
constexpr T t2 = c.at(2);
static_assert (t2 == 3.5, "");
}
#endif
#if TEST_STD_VER > 14
{
static_assert (check_idx(0, 1), "");
static_assert (check_idx(1, 2), "");
static_assert (check_idx(2, 3.5), "");
}
#endif
return 0;
return true;
}
void test_exceptions()
{
#ifndef TEST_HAS_NO_EXCEPTIONS
{
std::array<int, 4> array = {1, 2, 3, 4};
try {
TEST_IGNORE_NODISCARD array.at(4);
assert(false);
} catch (std::out_of_range const&) {
// pass
} catch (...) {
assert(false);
}
try {
TEST_IGNORE_NODISCARD array.at(5);
assert(false);
} catch (std::out_of_range const&) {
// pass
} catch (...) {
assert(false);
}
try {
TEST_IGNORE_NODISCARD array.at(6);
assert(false);
} catch (std::out_of_range const&) {
// pass
} catch (...) {
assert(false);
}
try {
TEST_IGNORE_NODISCARD array.at(-1);
assert(false);
} catch (std::out_of_range const&) {
// pass
} catch (...) {
assert(false);
}
}
{
std::array<int, 0> array = {};
try {
TEST_IGNORE_NODISCARD array.at(0);
assert(false);
} catch (std::out_of_range const&) {
// pass
} catch (...) {
assert(false);
}
}
#endif
}
int main(int, char**)
{
tests();
test_exceptions();
#if TEST_STD_VER >= 17
static_assert(tests(), "");
#endif
return 0;
}

View File

@@ -0,0 +1,109 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <array>
// const_reference at (size_type) const; // constexpr in C++14
#include <array>
#include <cassert>
#ifndef TEST_HAS_NO_EXCEPTIONS
#include <stdexcept>
#endif
#include "test_macros.h"
// std::array is explicitly allowed to be initialized with A a = { init-list };.
// Disable the missing braces warning for this reason.
#include "disable_missing_braces_warning.h"
TEST_CONSTEXPR_CXX14 bool tests()
{
{
typedef double T;
typedef std::array<T, 3> C;
C const c = {1, 2, 3.5};
typename C::const_reference r1 = c.at(0);
assert(r1 == 1);
typename C::const_reference r2 = c.at(2);
assert(r2 == 3.5);
}
return true;
}
void test_exceptions()
{
#ifndef TEST_HAS_NO_EXCEPTIONS
{
std::array<int, 4> const array = {1, 2, 3, 4};
try {
TEST_IGNORE_NODISCARD array.at(4);
assert(false);
} catch (std::out_of_range const&) {
// pass
} catch (...) {
assert(false);
}
try {
TEST_IGNORE_NODISCARD array.at(5);
assert(false);
} catch (std::out_of_range const&) {
// pass
} catch (...) {
assert(false);
}
try {
TEST_IGNORE_NODISCARD array.at(6);
assert(false);
} catch (std::out_of_range const&) {
// pass
} catch (...) {
assert(false);
}
try {
TEST_IGNORE_NODISCARD array.at(-1);
assert(false);
} catch (std::out_of_range const&) {
// pass
} catch (...) {
assert(false);
}
}
{
std::array<int, 0> array = {};
try {
TEST_IGNORE_NODISCARD array.at(0);
assert(false);
} catch (std::out_of_range const&) {
// pass
} catch (...) {
assert(false);
}
}
#endif
}
int main(int, char**)
{
tests();
test_exceptions();
#if TEST_STD_VER >= 14
static_assert(tests(), "");
#endif
return 0;
}

View File

@@ -1,53 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <array>
// iterator begin();
#include <array>
#include <cassert>
#include "test_macros.h"
// std::array is explicitly allowed to be initialized with A a = { init-list };.
// Disable the missing braces warning for this reason.
#include "disable_missing_braces_warning.h"
struct NoDefault {
NoDefault(int) {}
};
int main(int, char**)
{
{
typedef double T;
typedef std::array<T, 3> C;
C c = {1, 2, 3.5};
C::iterator i;
i = c.begin();
assert(*i == 1);
assert(&*i == c.data());
*i = 5.5;
assert(c[0] == 5.5);
}
{
typedef NoDefault T;
typedef std::array<T, 0> C;
C c = {};
C::iterator ib, ie;
ib = c.begin();
ie = c.end();
assert(ib == ie);
LIBCPP_ASSERT(ib != nullptr);
LIBCPP_ASSERT(ie != nullptr);
}
return 0;
}

View File

@@ -8,17 +8,15 @@
// <array>
// These are all constexpr in C++20
// bool operator==(array<T, N> const&, array<T, N> const&);
// bool operator!=(array<T, N> const&, array<T, N> const&);
// bool operator<(array<T, N> const&, array<T, N> const&);
// bool operator<=(array<T, N> const&, array<T, N> const&);
// bool operator>(array<T, N> const&, array<T, N> const&);
// bool operator>=(array<T, N> const&, array<T, N> const&);
// bool operator==(array<T, N> const&, array<T, N> const&); // constexpr in C++20
// bool operator!=(array<T, N> const&, array<T, N> const&); // constexpr in C++20
// bool operator<(array<T, N> const&, array<T, N> const&); // constexpr in C++20
// bool operator<=(array<T, N> const&, array<T, N> const&); // constexpr in C++20
// bool operator>(array<T, N> const&, array<T, N> const&); // constexpr in C++20
// bool operator>=(array<T, N> const&, array<T, N> const&); // constexpr in C++20
#include <array>
#include <vector>
#include <cassert>
#include "test_macros.h"
@@ -28,36 +26,33 @@
// Disable the missing braces warning for this reason.
#include "disable_missing_braces_warning.h"
TEST_CONSTEXPR_CXX20 bool tests()
{
{
typedef std::array<int, 3> C;
C c1 = {1, 2, 3};
C c2 = {1, 2, 3};
C c3 = {3, 2, 1};
C c4 = {1, 2, 1};
assert(testComparisons6(c1, c2, true, false));
assert(testComparisons6(c1, c3, false, true));
assert(testComparisons6(c1, c4, false, false));
}
{
typedef std::array<int, 0> C;
C c1 = {};
C c2 = {};
assert(testComparisons6(c1, c2, true, false));
}
return true;
}
int main(int, char**)
{
{
typedef int T;
typedef std::array<T, 3> C;
C c1 = {1, 2, 3};
C c2 = {1, 2, 3};
C c3 = {3, 2, 1};
C c4 = {1, 2, 1};
assert(testComparisons6(c1, c2, true, false));
assert(testComparisons6(c1, c3, false, true));
assert(testComparisons6(c1, c4, false, false));
}
{
typedef int T;
typedef std::array<T, 0> C;
C c1 = {};
C c2 = {};
assert(testComparisons6(c1, c2, true, false));
}
#if TEST_STD_VER > 17
{
constexpr std::array<int, 3> a1 = {1, 2, 3};
constexpr std::array<int, 3> a2 = {2, 3, 4};
static_assert(testComparisons6(a1, a1, true, false), "");
static_assert(testComparisons6(a1, a2, false, true), "");
static_assert(testComparisons6(a2, a1, false, false), "");
}
tests();
#if TEST_STD_VER >= 20
static_assert(tests(), "");
#endif
return 0;
return 0;
}

View File

@@ -15,20 +15,33 @@
#include "test_macros.h"
template <class C>
void test_contiguous ( const C &c )
template <class Container>
TEST_CONSTEXPR_CXX14 void assert_contiguous(Container const& c)
{
for ( size_t i = 0; i < c.size(); ++i )
assert ( *(c.begin() + i) == *(std::addressof(*c.begin()) + i));
for (size_t i = 0; i < c.size(); ++i)
assert(*(c.begin() + i) == *(std::addressof(*c.begin()) + i));
}
TEST_CONSTEXPR_CXX17 bool tests()
{
assert_contiguous(std::array<double, 0>());
assert_contiguous(std::array<double, 1>());
assert_contiguous(std::array<double, 2>());
assert_contiguous(std::array<double, 3>());
assert_contiguous(std::array<char, 0>());
assert_contiguous(std::array<char, 1>());
assert_contiguous(std::array<char, 2>());
assert_contiguous(std::array<char, 3>());
return true;
}
int main(int, char**)
{
{
typedef double T;
typedef std::array<T, 3> C;
test_contiguous (C());
}
return 0;
tests();
#if TEST_STD_VER >= 17 // begin() & friends are constexpr in >= C++17 only
static_assert(tests(), "");
#endif
return 0;
}

View File

@@ -10,28 +10,45 @@
// class array
// bool empty() const noexcept;
// constexpr bool empty() const noexcept;
#include <array>
#include <cassert>
#include "test_macros.h"
#include "min_allocator.h"
TEST_CONSTEXPR_CXX14 bool tests()
{
{
typedef std::array<int, 2> C;
C c = {};
ASSERT_NOEXCEPT(c.empty());
assert(!c.empty());
}
{
typedef std::array<int, 0> C;
C c = {};
ASSERT_NOEXCEPT(c.empty());
assert(c.empty());
}
return true;
}
int main(int, char**)
{
{
typedef std::array<int, 2> C;
C c;
ASSERT_NOEXCEPT(c.empty());
assert(!c.empty());
}
{
typedef std::array<int, 0> C;
C c;
ASSERT_NOEXCEPT(c.empty());
assert( c.empty());
}
tests();
#if TEST_STD_VER >= 14
static_assert(tests(), "");
#endif
return 0;
#if TEST_STD_VER >= 11
// Sanity check for constexpr in C++11
{
constexpr std::array<int, 3> array = {};
static_assert(!array.empty(), "");
}
#endif
return 0;
}

View File

@@ -8,10 +8,8 @@
// <array>
// reference front(); // constexpr in C++17
// reference back(); // constexpr in C++17
// const_reference front(); // constexpr in C++14
// const_reference back(); // constexpr in C++14
// reference front(); // constexpr in C++17
// reference back(); // constexpr in C++17
#include <array>
#include <cassert>
@@ -22,21 +20,8 @@
// Disable the missing braces warning for this reason.
#include "disable_missing_braces_warning.h"
#if TEST_STD_VER > 14
constexpr bool check_front( double val )
{
std::array<double, 3> arr = {1, 2, 3.5};
return arr.front() == val;
}
constexpr bool check_back( double val )
{
std::array<double, 3> arr = {1, 2, 3.5};
return arr.back() == val;
}
#endif
int main(int, char**)
TEST_CONSTEXPR_CXX17 bool tests()
{
{
typedef double T;
@@ -55,74 +40,39 @@ int main(int, char**)
}
{
typedef double T;
typedef std::array<T, 3> C;
const C c = {1, 2, 3.5};
C::const_reference r1 = c.front();
assert(r1 == 1);
C::const_reference r2 = c.back();
assert(r2 == 3.5);
typedef std::array<T, 0> C;
C c = {};
ASSERT_SAME_TYPE(decltype(c.back()), C::reference);
LIBCPP_ASSERT_NOEXCEPT(c.back());
ASSERT_SAME_TYPE(decltype(c.front()), C::reference);
LIBCPP_ASSERT_NOEXCEPT(c.front());
if (c.size() > (0)) { // always false
TEST_IGNORE_NODISCARD c.front();
TEST_IGNORE_NODISCARD c.back();
}
}
{
typedef double T;
typedef std::array<T, 0> C;
C c = {};
C const& cc = c;
ASSERT_SAME_TYPE(decltype( c.back()), typename C::reference);
ASSERT_SAME_TYPE(decltype(cc.back()), typename C::const_reference);
LIBCPP_ASSERT_NOEXCEPT( c.back());
LIBCPP_ASSERT_NOEXCEPT( cc.back());
ASSERT_SAME_TYPE(decltype( c.front()), typename C::reference);
ASSERT_SAME_TYPE(decltype(cc.front()), typename C::const_reference);
LIBCPP_ASSERT_NOEXCEPT( c.front());
LIBCPP_ASSERT_NOEXCEPT( cc.front());
if (c.size() > (0)) { // always false
TEST_IGNORE_NODISCARD c.front();
TEST_IGNORE_NODISCARD c.back();
TEST_IGNORE_NODISCARD cc.front();
TEST_IGNORE_NODISCARD cc.back();
}
}
{
typedef double T;
typedef std::array<const T, 0> C;
C c = {{}};
C const& cc = c;
ASSERT_SAME_TYPE(decltype( c.back()), typename C::reference);
ASSERT_SAME_TYPE(decltype(cc.back()), typename C::const_reference);
LIBCPP_ASSERT_NOEXCEPT( c.back());
LIBCPP_ASSERT_NOEXCEPT( cc.back());
ASSERT_SAME_TYPE(decltype( c.front()), typename C::reference);
ASSERT_SAME_TYPE(decltype(cc.front()), typename C::const_reference);
LIBCPP_ASSERT_NOEXCEPT( c.front());
LIBCPP_ASSERT_NOEXCEPT( cc.front());
if (c.size() > (0)) {
TEST_IGNORE_NODISCARD c.front();
TEST_IGNORE_NODISCARD c.back();
TEST_IGNORE_NODISCARD cc.front();
TEST_IGNORE_NODISCARD cc.back();
}
}
#if TEST_STD_VER > 11
{
typedef double T;
typedef std::array<T, 3> C;
constexpr C c = {1, 2, 3.5};
constexpr T t1 = c.front();
static_assert (t1 == 1, "");
constexpr T t2 = c.back();
static_assert (t2 == 3.5, "");
typedef std::array<const T, 0> C;
C c = {};
ASSERT_SAME_TYPE(decltype( c.back()), C::reference);
LIBCPP_ASSERT_NOEXCEPT( c.back());
ASSERT_SAME_TYPE(decltype( c.front()), C::reference);
LIBCPP_ASSERT_NOEXCEPT( c.front());
if (c.size() > (0)) {
TEST_IGNORE_NODISCARD c.front();
TEST_IGNORE_NODISCARD c.back();
}
}
#endif
#if TEST_STD_VER > 14
{
static_assert (check_front(1), "");
static_assert (check_back (3.5), "");
}
#endif
return 0;
return true;
}
int main(int, char**)
{
tests();
#if TEST_STD_VER >= 17
static_assert(tests(), "");
#endif
return 0;
}

View File

@@ -0,0 +1,73 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <array>
// const_reference front() const; // constexpr in C++14
// const_reference back() const; // constexpr in C++14
#include <array>
#include <cassert>
#include "test_macros.h"
// std::array is explicitly allowed to be initialized with A a = { init-list };.
// Disable the missing braces warning for this reason.
#include "disable_missing_braces_warning.h"
TEST_CONSTEXPR_CXX14 bool tests()
{
{
typedef double T;
typedef std::array<T, 3> C;
C const c = {1, 2, 3.5};
C::const_reference r1 = c.front();
assert(r1 == 1);
C::const_reference r2 = c.back();
assert(r2 == 3.5);
}
{
typedef double T;
typedef std::array<T, 0> C;
C const c = {};
ASSERT_SAME_TYPE(decltype(c.back()), C::const_reference);
LIBCPP_ASSERT_NOEXCEPT(c.back());
ASSERT_SAME_TYPE(decltype(c.front()), C::const_reference);
LIBCPP_ASSERT_NOEXCEPT(c.front());
if (c.size() > (0)) { // always false
TEST_IGNORE_NODISCARD c.front();
TEST_IGNORE_NODISCARD c.back();
}
}
{
typedef double T;
typedef std::array<const T, 0> C;
C const c = {};
ASSERT_SAME_TYPE(decltype(c.back()), C::const_reference);
LIBCPP_ASSERT_NOEXCEPT(c.back());
ASSERT_SAME_TYPE(decltype(c.front()), C::const_reference);
LIBCPP_ASSERT_NOEXCEPT(c.front());
if (c.size() > (0)) {
TEST_IGNORE_NODISCARD c.front();
TEST_IGNORE_NODISCARD c.back();
}
}
return true;
}
int main(int, char**)
{
tests();
#if TEST_STD_VER >= 14
static_assert(tests(), "");
#endif
return 0;
}

View File

@@ -8,11 +8,8 @@
// <array>
// reference operator[] (size_type)
// const_reference operator[] (size_type); // constexpr in C++14
// reference at (size_type)
// const_reference at (size_type); // constexpr in C++14
// Libc++ marks these as noexcept
// reference operator[](size_type); // constexpr in C++17
// Libc++ marks it as noexcept
#include <array>
#include <cassert>
@@ -23,15 +20,8 @@
// Disable the missing braces warning for this reason.
#include "disable_missing_braces_warning.h"
#if TEST_STD_VER > 14
constexpr bool check_idx( size_t idx, double val )
{
std::array<double, 3> arr = {1, 2, 3.5};
return arr[idx] == val;
}
#endif
int main(int, char**)
TEST_CONSTEXPR_CXX17 bool tests()
{
{
typedef double T;
@@ -49,72 +39,41 @@ int main(int, char**)
r2 = 7.5;
assert(c.back() == 7.5);
}
// Test operator[] "works" on zero sized arrays
{
typedef double T;
typedef std::array<T, 3> C;
const C c = {1, 2, 3.5};
LIBCPP_ASSERT_NOEXCEPT(c[0]);
ASSERT_SAME_TYPE(C::const_reference, decltype(c[0]));
C::const_reference r1 = c[0];
assert(r1 == 1);
C::const_reference r2 = c[2];
assert(r2 == 3.5);
}
{ // Test operator[] "works" on zero sized arrays
typedef double T;
typedef std::array<T, 0> C;
C c = {};
C const& cc = c;
LIBCPP_ASSERT_NOEXCEPT(c[0]);
LIBCPP_ASSERT_NOEXCEPT(cc[0]);
ASSERT_SAME_TYPE(C::reference, decltype(c[0]));
ASSERT_SAME_TYPE(C::const_reference, decltype(cc[0]));
if (c.size() > (0)) { // always false
C::reference r1 = c[0];
C::const_reference r2 = cc[0];
((void)r1);
((void)r2);
{
typedef double T;
typedef std::array<T, 0> C;
C c = {};
LIBCPP_ASSERT_NOEXCEPT(c[0]);
ASSERT_SAME_TYPE(C::reference, decltype(c[0]));
if (c.size() > (0)) { // always false
C::reference r = c[0];
(void)r;
}
}
{
typedef double T;
typedef std::array<const T, 0> C;
C c = {};
LIBCPP_ASSERT_NOEXCEPT(c[0]);
ASSERT_SAME_TYPE(C::reference, decltype(c[0]));
if (c.size() > (0)) { // always false
C::reference r = c[0];
(void)r;
}
}
}
{ // Test operator[] "works" on zero sized arrays
typedef double T;
typedef std::array<const T, 0> C;
C c = {{}};
C const& cc = c;
LIBCPP_ASSERT_NOEXCEPT(c[0]);
LIBCPP_ASSERT_NOEXCEPT(cc[0]);
ASSERT_SAME_TYPE(C::reference, decltype(c[0]));
ASSERT_SAME_TYPE(C::const_reference, decltype(cc[0]));
if (c.size() > (0)) { // always false
C::reference r1 = c[0];
C::const_reference r2 = cc[0];
((void)r1);
((void)r2);
}
}
#if TEST_STD_VER > 11
{
typedef double T;
typedef std::array<T, 3> C;
constexpr C c = {1, 2, 3.5};
LIBCPP_ASSERT_NOEXCEPT(c[0]);
ASSERT_SAME_TYPE(C::const_reference, decltype(c[0]));
constexpr T t1 = c[0];
static_assert (t1 == 1, "");
constexpr T t2 = c[2];
static_assert (t2 == 3.5, "");
}
#endif
#if TEST_STD_VER > 14
{
static_assert (check_idx(0, 1), "");
static_assert (check_idx(1, 2), "");
static_assert (check_idx(2, 3.5), "");
}
#endif
return 0;
return true;
}
int main(int, char**)
{
tests();
#if TEST_STD_VER >= 17
static_assert(tests(), "");
#endif
return 0;
}

View File

@@ -0,0 +1,73 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <array>
// const_reference operator[](size_type) const; // constexpr in C++14
// Libc++ marks it as noexcept
#include <array>
#include <cassert>
#include "test_macros.h"
// std::array is explicitly allowed to be initialized with A a = { init-list };.
// Disable the missing braces warning for this reason.
#include "disable_missing_braces_warning.h"
TEST_CONSTEXPR_CXX14 bool tests()
{
{
typedef double T;
typedef std::array<T, 3> C;
C const c = {1, 2, 3.5};
LIBCPP_ASSERT_NOEXCEPT(c[0]);
ASSERT_SAME_TYPE(C::const_reference, decltype(c[0]));
C::const_reference r1 = c[0];
assert(r1 == 1);
C::const_reference r2 = c[2];
assert(r2 == 3.5);
}
// Test operator[] "works" on zero sized arrays
{
{
typedef double T;
typedef std::array<T, 0> C;
C const c = {};
LIBCPP_ASSERT_NOEXCEPT(c[0]);
ASSERT_SAME_TYPE(C::const_reference, decltype(c[0]));
if (c.size() > (0)) { // always false
C::const_reference r = c[0];
(void)r;
}
}
{
typedef double T;
typedef std::array<T const, 0> C;
C const c = {};
LIBCPP_ASSERT_NOEXCEPT(c[0]);
ASSERT_SAME_TYPE(C::const_reference, decltype(c[0]));
if (c.size() > (0)) { // always false
C::const_reference r = c[0];
(void)r;
}
}
}
return true;
}
int main(int, char**)
{
tests();
#if TEST_STD_VER >= 14
static_assert(tests(), "");
#endif
return 0;
}

View File

@@ -8,7 +8,20 @@
// <array>
// iterator, const_iterator
// iterator begin() noexcept; // constexpr in C++17
// const_iterator begin() const noexcept; // constexpr in C++17
// iterator end() noexcept; // constexpr in C++17
// const_iterator end() const noexcept; // constexpr in C++17
//
// reverse_iterator rbegin() noexcept; // constexpr in C++17
// const_reverse_iterator rbegin() const noexcept; // constexpr in C++17
// reverse_iterator rend() noexcept; // constexpr in C++17
// const_reverse_iterator rend() const noexcept; // constexpr in C++17
//
// const_iterator cbegin() const noexcept; // constexpr in C++17
// const_iterator cend() const noexcept; // constexpr in C++17
// const_reverse_iterator crbegin() const noexcept; // constexpr in C++17
// const_reverse_iterator crend() const noexcept; // constexpr in C++17
#include <array>
#include <iterator>
@@ -20,127 +33,157 @@
// Disable the missing braces warning for this reason.
#include "disable_missing_braces_warning.h"
int main(int, char**)
struct NoDefault {
TEST_CONSTEXPR NoDefault(int) { }
};
TEST_CONSTEXPR_CXX17 bool tests()
{
{
typedef std::array<int, 5> C;
C c;
C::iterator i;
i = c.begin();
C::const_iterator j;
j = c.cbegin();
assert(i == j);
typedef std::array<int, 5> C;
C array = {};
typename C::iterator i = array.begin();
typename C::const_iterator j = array.cbegin();
assert(i == j);
}
{
typedef std::array<int, 0> C;
C c;
C::iterator i;
i = c.begin();
C::const_iterator j;
j = c.cbegin();
assert(i == j);
typedef std::array<int, 0> C;
C array = {};
typename C::iterator i = array.begin();
typename C::const_iterator j = array.cbegin();
assert(i == j);
LIBCPP_ASSERT(i != nullptr);
LIBCPP_ASSERT(j != nullptr);
}
#if TEST_STD_VER > 11
{
typedef std::array<int, 0> C;
C array = {};
typename C::iterator i = array.begin();
typename C::const_iterator j = array.cbegin();
assert(i == array.end());
assert(j == array.cend());
LIBCPP_ASSERT(i != nullptr);
LIBCPP_ASSERT(j != nullptr);
}
{
typedef std::array<int, 1> C;
C array = {1};
typename C::iterator i = array.begin();
assert(*i == 1);
assert(&*i == array.data());
*i = 99;
assert(array[0] == 99);
}
{
typedef std::array<int, 2> C;
C array = {1, 2};
typename C::iterator i = array.begin();
assert(*i == 1);
assert(&*i == array.data());
*i = 99;
assert(array[0] == 99);
assert(array[1] == 2);
}
{
typedef std::array<double, 3> C;
C array = {1, 2, 3.5};
typename C::iterator i = array.begin();
assert(*i == 1);
assert(&*i == array.data());
*i = 5.5;
assert(array[0] == 5.5);
assert(array[1] == 2.0);
}
{
typedef std::array<NoDefault, 0> C;
C array = {};
typename C::iterator ib = array.begin();
typename C::iterator ie = array.end();
assert(ib == ie);
LIBCPP_ASSERT(ib != nullptr);
LIBCPP_ASSERT(ie != nullptr);
}
#if TEST_STD_VER >= 14
{ // N3644 testing
{
typedef std::array<int, 5> C;
C::iterator ii1{}, ii2{};
C::iterator ii4 = ii1;
C::const_iterator cii{};
assert ( ii1 == ii2 );
assert ( ii1 == ii4 );
assert ( ii1 == cii );
typedef std::array<int, 5> C;
C::iterator ii1{}, ii2{};
C::iterator ii4 = ii1;
C::const_iterator cii{};
assert(ii1 == ii2);
assert(ii1 == ii4);
assert(ii1 == cii);
assert ( !(ii1 != ii2 ));
assert ( !(ii1 != cii ));
assert(!(ii1 != ii2));
assert(!(ii1 != cii));
C c;
assert ( c.begin() == std::begin(c));
assert ( c.cbegin() == std::cbegin(c));
assert ( c.rbegin() == std::rbegin(c));
assert ( c.crbegin() == std::crbegin(c));
assert ( c.end() == std::end(c));
assert ( c.cend() == std::cend(c));
assert ( c.rend() == std::rend(c));
assert ( c.crend() == std::crend(c));
C c = {};
assert(c.begin() == std::begin(c));
assert(c.cbegin() == std::cbegin(c));
assert(c.rbegin() == std::rbegin(c));
assert(c.crbegin() == std::crbegin(c));
assert(c.end() == std::end(c));
assert(c.cend() == std::cend(c));
assert(c.rend() == std::rend(c));
assert(c.crend() == std::crend(c));
assert ( std::begin(c) != std::end(c));
assert ( std::rbegin(c) != std::rend(c));
assert ( std::cbegin(c) != std::cend(c));
assert ( std::crbegin(c) != std::crend(c));
assert(std::begin(c) != std::end(c));
assert(std::rbegin(c) != std::rend(c));
assert(std::cbegin(c) != std::cend(c));
assert(std::crbegin(c) != std::crend(c));
}
{
typedef std::array<int, 0> C;
C::iterator ii1{}, ii2{};
C::iterator ii4 = ii1;
C::const_iterator cii{};
assert ( ii1 == ii2 );
assert ( ii1 == ii4 );
typedef std::array<int, 0> C;
C::iterator ii1{}, ii2{};
C::iterator ii4 = ii1;
C::const_iterator cii{};
assert(ii1 == ii2);
assert(ii1 == ii4);
assert (!(ii1 != ii2 ));
assert(!(ii1 != ii2));
assert ( (ii1 == cii ));
assert ( (cii == ii1 ));
assert (!(ii1 != cii ));
assert (!(cii != ii1 ));
assert (!(ii1 < cii ));
assert (!(cii < ii1 ));
assert ( (ii1 <= cii ));
assert ( (cii <= ii1 ));
assert (!(ii1 > cii ));
assert (!(cii > ii1 ));
assert ( (ii1 >= cii ));
assert ( (cii >= ii1 ));
assert (cii - ii1 == 0);
assert (ii1 - cii == 0);
assert( (ii1 == cii));
assert( (cii == ii1));
assert(!(ii1 != cii));
assert(!(cii != ii1));
assert(!(ii1 < cii));
assert(!(cii < ii1));
assert( (ii1 <= cii));
assert( (cii <= ii1));
assert(!(ii1 > cii));
assert(!(cii > ii1));
assert( (ii1 >= cii));
assert( (cii >= ii1));
assert(cii - ii1 == 0);
assert(ii1 - cii == 0);
C c;
assert ( c.begin() == std::begin(c));
assert ( c.cbegin() == std::cbegin(c));
assert ( c.rbegin() == std::rbegin(c));
assert ( c.crbegin() == std::crbegin(c));
assert ( c.end() == std::end(c));
assert ( c.cend() == std::cend(c));
assert ( c.rend() == std::rend(c));
assert ( c.crend() == std::crend(c));
C c = {};
assert(c.begin() == std::begin(c));
assert(c.cbegin() == std::cbegin(c));
assert(c.rbegin() == std::rbegin(c));
assert(c.crbegin() == std::crbegin(c));
assert(c.end() == std::end(c));
assert(c.cend() == std::cend(c));
assert(c.rend() == std::rend(c));
assert(c.crend() == std::crend(c));
assert ( std::begin(c) == std::end(c));
assert ( std::rbegin(c) == std::rend(c));
assert ( std::cbegin(c) == std::cend(c));
assert ( std::crbegin(c) == std::crend(c));
assert(std::begin(c) == std::end(c));
assert(std::rbegin(c) == std::rend(c));
assert(std::cbegin(c) == std::cend(c));
assert(std::crbegin(c) == std::crend(c));
}
}
#endif
#if TEST_STD_VER > 14
{
typedef std::array<int, 5> C;
constexpr C c{0,1,2,3,4};
return true;
}
static_assert ( c.begin() == std::begin(c), "");
static_assert ( c.cbegin() == std::cbegin(c), "");
static_assert ( c.end() == std::end(c), "");
static_assert ( c.cend() == std::cend(c), "");
static_assert ( c.rbegin() == std::rbegin(c), "");
static_assert ( c.crbegin() == std::crbegin(c), "");
static_assert ( c.rend() == std::rend(c), "");
static_assert ( c.crend() == std::crend(c), "");
static_assert ( std::begin(c) != std::end(c), "");
static_assert ( std::rbegin(c) != std::rend(c), "");
static_assert ( std::cbegin(c) != std::cend(c), "");
static_assert ( std::crbegin(c) != std::crend(c), "");
static_assert ( *c.begin() == 0, "");
static_assert ( *c.rbegin() == 4, "");
static_assert ( *std::begin(c) == 0, "" );
static_assert ( *std::cbegin(c) == 0, "" );
static_assert ( *std::rbegin(c) == 4, "" );
static_assert ( *std::crbegin(c) == 4, "" );
}
int main(int, char**)
{
tests();
#if TEST_STD_VER >= 17
static_assert(tests(), "");
#endif
return 0;
}

View File

@@ -10,28 +10,45 @@
// class array
// bool max_size() const noexcept;
// constexpr bool max_size() const noexcept;
#include <array>
#include <cassert>
#include "test_macros.h"
#include "min_allocator.h"
TEST_CONSTEXPR_CXX14 bool tests()
{
{
typedef std::array<int, 2> C;
C c = {};
ASSERT_NOEXCEPT(c.max_size());
assert(c.max_size() == 2);
}
{
typedef std::array<int, 0> C;
C c = {};
ASSERT_NOEXCEPT(c.max_size());
assert(c.max_size() == 0);
}
return true;
}
int main(int, char**)
{
{
typedef std::array<int, 2> C;
C c;
ASSERT_NOEXCEPT(c.max_size());
assert(c.max_size() == 2);
}
{
typedef std::array<int, 0> C;
C c;
ASSERT_NOEXCEPT(c.max_size());
assert(c.max_size() == 0);
}
tests();
#if TEST_STD_VER >= 14
static_assert(tests(), "");
#endif
return 0;
#if TEST_STD_VER >= 11
// Sanity check for constexpr in C++11
{
constexpr std::array<int, 3> array = {};
static_assert(array.max_size() == 3, "");
}
#endif
return 0;
}

View File

@@ -34,12 +34,6 @@ void test() {
static_assert(sizeof(ArrayT) == sizeof(CArrayT), "");
static_assert(sizeof(ArrayT) == sizeof(MyArrayT), "");
static_assert(TEST_ALIGNOF(ArrayT) == TEST_ALIGNOF(MyArrayT), "");
#if defined(_LIBCPP_VERSION)
ArrayT a;
((void)a);
static_assert(sizeof(ArrayT) == sizeof(a.__elems_), "");
static_assert(TEST_ALIGNOF(ArrayT) == __alignof__(a.__elems_), "");
#endif
}
template <class T>
@@ -67,8 +61,6 @@ struct TEST_ALIGNAS(TEST_ALIGNOF(std::max_align_t) * 2) TestType2 {
};
#endif
//static_assert(sizeof(void*) == 4, "");
int main(int, char**) {
test_type<char>();
test_type<int>();

View File

@@ -15,6 +15,7 @@
/* Constant Value
__cpp_lib_array_constexpr 201603L [C++17]
201811L [C++2a]
__cpp_lib_constexpr_misc 201811L [C++2a]
__cpp_lib_nonmember_container_access 201411L [C++17]
__cpp_lib_to_array 201907L [C++2a]
@@ -88,8 +89,8 @@
# ifndef __cpp_lib_array_constexpr
# error "__cpp_lib_array_constexpr should be defined in c++2a"
# endif
# if __cpp_lib_array_constexpr != 201603L
# error "__cpp_lib_array_constexpr should have the value 201603L in c++2a"
# if __cpp_lib_array_constexpr != 201811L
# error "__cpp_lib_array_constexpr should have the value 201811L in c++2a"
# endif
# if !defined(_LIBCPP_VERSION)

View File

@@ -15,6 +15,7 @@
/* Constant Value
__cpp_lib_array_constexpr 201603L [C++17]
201811L [C++2a]
__cpp_lib_constexpr_misc 201811L [C++2a]
__cpp_lib_make_reverse_iterator 201402L [C++14]
__cpp_lib_nonmember_container_access 201411L [C++17]
@@ -126,8 +127,8 @@
# ifndef __cpp_lib_array_constexpr
# error "__cpp_lib_array_constexpr should be defined in c++2a"
# endif
# if __cpp_lib_array_constexpr != 201603L
# error "__cpp_lib_array_constexpr should have the value 201603L in c++2a"
# if __cpp_lib_array_constexpr != 201811L
# error "__cpp_lib_array_constexpr should have the value 201811L in c++2a"
# endif
# if !defined(_LIBCPP_VERSION)

View File

@@ -19,6 +19,7 @@
__cpp_lib_any 201606L [C++17]
__cpp_lib_apply 201603L [C++17]
__cpp_lib_array_constexpr 201603L [C++17]
201811L [C++2a]
__cpp_lib_as_const 201510L [C++17]
__cpp_lib_atomic_is_always_lock_free 201603L [C++17]
__cpp_lib_atomic_ref 201806L [C++2a]
@@ -1537,8 +1538,8 @@
# ifndef __cpp_lib_array_constexpr
# error "__cpp_lib_array_constexpr should be defined in c++2a"
# endif
# if __cpp_lib_array_constexpr != 201603L
# error "__cpp_lib_array_constexpr should have the value 201603L in c++2a"
# if __cpp_lib_array_constexpr != 201811L
# error "__cpp_lib_array_constexpr should have the value 201811L in c++2a"
# endif
# ifndef __cpp_lib_as_const

View File

@@ -149,6 +149,12 @@
# define TEST_CONSTEXPR_CXX14
#endif
#if TEST_STD_VER >= 17
# define TEST_CONSTEXPR_CXX17 constexpr
#else
# define TEST_CONSTEXPR_CXX17
#endif
#if TEST_STD_VER >= 20
# define TEST_CONSTEXPR_CXX20 constexpr
#else

View File

@@ -409,6 +409,7 @@ feature_test_macros = sorted([ add_version_header(x) for x in [
{"name": "__cpp_lib_array_constexpr",
"values": {
"c++17": int(201603),
"c++2a": int(201811),
},
"headers": ["iterator", "array"],
},