Index: include/array =================================================================== --- include/array +++ include/array @@ -247,11 +247,21 @@ typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; +#if _LIBCPP_STD_VER > 14 + union __wrapper { + constexpr __wrapper(): __b() {} + ~__wrapper() = default; + + bool __b; + _Tp __t; + } __w; +#else typedef typename conditional::value, const char, char>::type _CharType; struct _ArrayInStructT { _Tp __data_[1]; }; _ALIGNAS_TYPE(_ArrayInStructT) _CharType __elems_[sizeof(_ArrayInStructT)]; +#endif // _LIBCPP_STD_VER > 14 // No explicit construct/copy/destroy for aggregate type _LIBCPP_INLINE_VISIBILITY void fill(const value_type&) { @@ -266,31 +276,31 @@ } // 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: @@ -302,7 +312,7 @@ _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::operator[] on a zero-sized array"); _LIBCPP_UNREACHABLE(); @@ -314,46 +324,46 @@ _LIBCPP_UNREACHABLE(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference at(size_type) { __throw_out_of_range("array::at"); _LIBCPP_UNREACHABLE(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 const_reference at(size_type) const { __throw_out_of_range("array::at"); _LIBCPP_UNREACHABLE(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference front() _NOEXCEPT { _LIBCPP_ASSERT(false, "cannot call array::front() on a zero-sized array"); _LIBCPP_UNREACHABLE(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 const_reference front() const _NOEXCEPT { _LIBCPP_ASSERT(false, "cannot call array::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::back() on a zero-sized array"); _LIBCPP_UNREACHABLE(); } - _LIBCPP_INLINE_VISIBILITY + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 const_reference back() const _NOEXCEPT { _LIBCPP_ASSERT(false, "cannot call array::back() on a zero-sized array"); _LIBCPP_UNREACHABLE(); } - _LIBCPP_INLINE_VISIBILITY - value_type* data() _NOEXCEPT {return reinterpret_cast(__elems_);} - _LIBCPP_INLINE_VISIBILITY - const value_type* data() const _NOEXCEPT {return reinterpret_cast(__elems_);} + _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;} }; Index: test/std/containers/sequences/array/size_and_alignment.pass.cpp =================================================================== --- test/std/containers/sequences/array/size_and_alignment.pass.cpp +++ test/std/containers/sequences/array/size_and_alignment.pass.cpp @@ -20,33 +20,53 @@ #include "test_macros.h" +template +inline constexpr bool has_consexpr_members(A const& arr) { + return arr.begin() && + arr.end() && + arr.rbegin() == arr.rbegin() && + arr.rend() == arr.rend() && + arr.cbegin() && + arr.cend() && + arr.crbegin() == arr.crbegin() && + arr.crend() == arr.crend() && + (arr.size() || !arr.size()) && + (arr.max_size() || !arr.max_size()) && + (arr.empty() || !arr.empty()) && + arr.data() && true; +} template struct MyArray { - T elems[Size]; + T elems[Size]; }; template void test() { - typedef T CArrayT[Size == 0 ? 1 : Size]; - typedef std::array ArrayT; - typedef MyArray MyArrayT; - 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_), ""); + typedef T CArrayT[Size == 0 ? 1 : Size]; + typedef std::array ArrayT; + typedef MyArray MyArrayT; + static_assert(sizeof(ArrayT) == sizeof(CArrayT), ""); + static_assert(sizeof(ArrayT) == sizeof(MyArrayT), ""); + static_assert(TEST_ALIGNOF(ArrayT) == TEST_ALIGNOF(MyArrayT), ""); +#if defined(_LIBCPP_VERSION) && Size > 0 // std::array.__elems_ does not exist. + ArrayT a; + ((void)a); + static_assert(sizeof(ArrayT) == sizeof(a.__elems_), ""); + static_assert(TEST_ALIGNOF(ArrayT) == __alignof__(a.__elems_), ""); +#endif +#if TEST_STD_VER > 17 + const std::array arr {}; + static_assert(has_consexpr_members(arr)); #endif + static_assert(std::is_aggregate::value); } template void test_type() { - test(); - test(); - test(); + test(); + test(); + test(); } struct TEST_ALIGNAS(TEST_ALIGNOF(std::max_align_t) * 2) TestType1 { @@ -54,19 +74,19 @@ }; struct TEST_ALIGNAS(TEST_ALIGNOF(std::max_align_t) * 2) TestType2 { - char data[1000]; + char data[1000]; }; //static_assert(sizeof(void*) == 4, ""); int main(int, char**) { - test_type(); - test_type(); - test_type(); - test_type(); - test_type(); - test_type(); - test_type(); + test_type(); + test_type(); + test_type(); + test_type(); + test_type(); + test_type(); + test_type(); - return 0; + return 0; }