2010-05-11 19:42:16 +00:00
|
|
|
// -*- C++ -*-
|
2021-11-17 16:25:01 -05:00
|
|
|
//===----------------------------------------------------------------------===//
|
2010-05-11 19:42:16 +00:00
|
|
|
//
|
2019-01-19 10:56:40 +00:00
|
|
|
// 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
|
2010-05-11 19:42:16 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef _LIBCPP_ARRAY
|
|
|
|
#define _LIBCPP_ARRAY
|
|
|
|
|
|
|
|
/*
|
|
|
|
array synopsis
|
|
|
|
|
|
|
|
namespace std
|
|
|
|
{
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class T, size_t N >
|
2010-05-11 19:42:16 +00:00
|
|
|
struct array
|
2010-08-22 00:02:43 +00:00
|
|
|
{
|
|
|
|
// types:
|
2024-07-30 20:24:11 +02:00
|
|
|
using value_type = T;
|
|
|
|
using pointer = T*;
|
|
|
|
using const_pointer = const T*;
|
|
|
|
using reference = T&;
|
|
|
|
using const_reference = const T&;
|
|
|
|
using size_type = size_t;
|
|
|
|
using difference_type = ptrdiff_t;
|
|
|
|
using iterator = implementation-defined;
|
|
|
|
using const_iterator = implementation-defined;
|
|
|
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
|
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
// No explicit construct/copy/destroy for aggregate type
|
2020-05-22 09:59:48 -04:00
|
|
|
void fill(const T& u); // constexpr in C++20
|
|
|
|
void swap(array& a) noexcept(is_nothrow_swappable_v<T>); // constexpr in C++20
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
// iterators:
|
2020-05-22 09:59:48 -04:00
|
|
|
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
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2020-05-22 09:59:48 -04:00
|
|
|
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
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2020-05-22 09:59:48 -04:00
|
|
|
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
|
2010-08-22 00:02:43 +00:00
|
|
|
|
|
|
|
// capacity:
|
2011-05-31 21:06:33 +00:00
|
|
|
constexpr size_type size() const noexcept;
|
|
|
|
constexpr size_type max_size() const noexcept;
|
2012-07-20 19:20:49 +00:00
|
|
|
constexpr bool empty() const noexcept;
|
2010-08-22 00:02:43 +00:00
|
|
|
|
|
|
|
// element access:
|
2020-05-22 09:59:48 -04:00
|
|
|
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(); // 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; // constexpr in C++17
|
|
|
|
const T* data() const noexcept; // constexpr in C++17
|
2010-05-11 19:42:16 +00:00
|
|
|
};
|
|
|
|
|
2020-05-22 09:59:48 -04:00
|
|
|
template <class T, class... U>
|
|
|
|
array(T, U...) -> array<T, 1 + sizeof...(U)>; // C++17
|
2018-05-18 21:01:04 +00:00
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class T, size_t N>
|
2020-05-22 09:59:48 -04:00
|
|
|
bool operator==(const array<T,N>& x, const array<T,N>& y); // constexpr in C++20
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class T, size_t N>
|
2023-05-06 15:41:41 +03:00
|
|
|
bool operator!=(const array<T,N>& x, const array<T,N>& y); // removed in C++20
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class T, size_t N>
|
2023-05-06 15:41:41 +03:00
|
|
|
bool operator<(const array<T,N>& x, const array<T,N>& y); // removed in C++20
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class T, size_t N>
|
2023-05-06 15:41:41 +03:00
|
|
|
bool operator>(const array<T,N>& x, const array<T,N>& y); // removed in C++20
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class T, size_t N>
|
2023-05-06 15:41:41 +03:00
|
|
|
bool operator<=(const array<T,N>& x, const array<T,N>& y); // removed in C++20
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class T, size_t N>
|
2023-05-06 15:41:41 +03:00
|
|
|
bool operator>=(const array<T,N>& x, const array<T,N>& y); // removed in C++20
|
|
|
|
template<class T, size_t N>
|
|
|
|
constexpr synth-three-way-result<T>
|
|
|
|
operator<=>(const array<T, N>& x, const array<T, N>& y); // since C++20
|
2010-08-22 00:02:43 +00:00
|
|
|
|
|
|
|
template <class T, size_t N >
|
2020-05-22 09:59:48 -04:00
|
|
|
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
|
2010-08-22 00:02:43 +00:00
|
|
|
|
2019-01-11 21:57:12 +00:00
|
|
|
template <class T> struct tuple_size;
|
2019-04-01 16:39:34 +00:00
|
|
|
template <size_t I, class T> struct tuple_element;
|
2010-05-11 19:42:16 +00:00
|
|
|
template <class T, size_t N> struct tuple_size<array<T, N>>;
|
2015-11-19 19:41:04 +00:00
|
|
|
template <size_t I, class T, size_t N> struct tuple_element<I, array<T, N>>;
|
2020-05-22 09:59:48 -04:00
|
|
|
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
|
2015-12-18 00:36:55 +00:00
|
|
|
template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexcept; // constexpr in C++14
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
} // std
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2024-12-21 13:01:48 +01:00
|
|
|
#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
|
|
|
|
# include <__cxx03/array>
|
|
|
|
#else
|
2024-12-10 16:02:12 +01:00
|
|
|
# include <__algorithm/equal.h>
|
|
|
|
# include <__algorithm/fill_n.h>
|
|
|
|
# include <__algorithm/lexicographical_compare.h>
|
|
|
|
# include <__algorithm/lexicographical_compare_three_way.h>
|
|
|
|
# include <__algorithm/swap_ranges.h>
|
|
|
|
# include <__assert>
|
|
|
|
# include <__config>
|
|
|
|
# include <__cstddef/ptrdiff_t.h>
|
|
|
|
# include <__fwd/array.h>
|
|
|
|
# include <__iterator/reverse_iterator.h>
|
|
|
|
# include <__iterator/static_bounded_iter.h>
|
|
|
|
# include <__iterator/wrap_iter.h>
|
|
|
|
# include <__tuple/sfinae_helpers.h>
|
|
|
|
# include <__type_traits/conditional.h>
|
|
|
|
# include <__type_traits/conjunction.h>
|
|
|
|
# include <__type_traits/enable_if.h>
|
|
|
|
# include <__type_traits/is_array.h>
|
|
|
|
# include <__type_traits/is_const.h>
|
|
|
|
# include <__type_traits/is_constructible.h>
|
|
|
|
# include <__type_traits/is_nothrow_constructible.h>
|
|
|
|
# include <__type_traits/is_same.h>
|
|
|
|
# include <__type_traits/is_swappable.h>
|
|
|
|
# include <__type_traits/is_trivially_relocatable.h>
|
|
|
|
# include <__type_traits/remove_cv.h>
|
|
|
|
# include <__utility/empty.h>
|
|
|
|
# include <__utility/integer_sequence.h>
|
|
|
|
# include <__utility/move.h>
|
|
|
|
# include <__utility/unreachable.h>
|
|
|
|
# include <stdexcept>
|
|
|
|
# include <version>
|
2010-05-11 19:42:16 +00:00
|
|
|
|
2022-06-16 22:43:46 +02:00
|
|
|
// standard-mandated includes
|
|
|
|
|
|
|
|
// [iterator.range]
|
2024-12-10 16:02:12 +01:00
|
|
|
# include <__iterator/access.h>
|
|
|
|
# include <__iterator/data.h>
|
|
|
|
# include <__iterator/empty.h>
|
|
|
|
# include <__iterator/reverse_access.h>
|
|
|
|
# include <__iterator/size.h>
|
2022-06-16 22:43:46 +02:00
|
|
|
|
|
|
|
// [array.syn]
|
2024-12-10 16:02:12 +01:00
|
|
|
# include <compare>
|
|
|
|
# include <initializer_list>
|
2022-06-16 22:43:46 +02:00
|
|
|
|
2022-09-05 14:38:24 +02:00
|
|
|
// [tuple.helper]
|
2024-12-10 16:02:12 +01:00
|
|
|
# include <__tuple/tuple_element.h>
|
|
|
|
# include <__tuple/tuple_size.h>
|
2022-09-05 14:38:24 +02:00
|
|
|
|
2024-12-10 16:02:12 +01:00
|
|
|
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
|
|
|
# pragma GCC system_header
|
|
|
|
# endif
|
2010-05-11 19:42:16 +00:00
|
|
|
|
[libc++] Fix missing and incorrect push/pop macros (#79204)
We recently noticed that the unwrap_iter.h file was pushing macros, but
it was pushing them again instead of popping them at the end of the
file. This led to libc++ basically swallowing any custom definition of
these macros in user code:
#define min HELLO
#include <algorithm>
// min is not HELLO anymore, it's not defined
While investigating this issue, I noticed that our push/pop pragmas were
actually entirely wrong too. Indeed, instead of pushing macros like
`move`, we'd push `move(int, int)` in the pragma, which is not a valid
macro name. As a result, we would not actually push macros like `move`
-- instead we'd simply undefine them. This led to the following code not
working:
#define move HELLO
#include <algorithm>
// move is not HELLO anymore
Fixing the pragma push/pop incantations led to a cascade of issues
because we use identifiers like `move` in a large number of places, and
all of these headers would now need to do the push/pop dance.
This patch fixes all these issues. First, it adds a check that we don't
swallow important names like min, max, move or refresh as explained
above. This is done by augmenting the existing
system_reserved_names.gen.py test to also check that the macros are what
we expect after including each header.
Second, it fixes the push/pop pragmas to work properly and adds missing
pragmas to all the files I could detect a failure in via the newly added
test.
rdar://121365472
2024-01-25 15:48:46 -05:00
|
|
|
_LIBCPP_PUSH_MACROS
|
2024-12-10 16:02:12 +01:00
|
|
|
# include <__undef_macros>
|
[libc++] Fix missing and incorrect push/pop macros (#79204)
We recently noticed that the unwrap_iter.h file was pushing macros, but
it was pushing them again instead of popping them at the end of the
file. This led to libc++ basically swallowing any custom definition of
these macros in user code:
#define min HELLO
#include <algorithm>
// min is not HELLO anymore, it's not defined
While investigating this issue, I noticed that our push/pop pragmas were
actually entirely wrong too. Indeed, instead of pushing macros like
`move`, we'd push `move(int, int)` in the pragma, which is not a valid
macro name. As a result, we would not actually push macros like `move`
-- instead we'd simply undefine them. This led to the following code not
working:
#define move HELLO
#include <algorithm>
// move is not HELLO anymore
Fixing the pragma push/pop incantations led to a cascade of issues
because we use identifiers like `move` in a large number of places, and
all of these headers would now need to do the push/pop dance.
This patch fixes all these issues. First, it adds a check that we don't
swallow important names like min, max, move or refresh as explained
above. This is done by augmenting the existing
system_reserved_names.gen.py test to also check that the macros are what
we expect after including each header.
Second, it fixes the push/pop pragmas to work properly and adds missing
pragmas to all the files I could detect a failure in via the newly added
test.
rdar://121365472
2024-01-25 15:48:46 -05:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Tp, size_t _Size>
|
2025-04-09 23:47:57 +02:00
|
|
|
struct array {
|
2025-01-08 17:12:59 +01:00
|
|
|
using __trivially_relocatable _LIBCPP_NODEBUG =
|
|
|
|
__conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value, array, void>;
|
2024-06-17 13:09:04 +02:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
// types:
|
2025-01-08 17:12:59 +01:00
|
|
|
using __self _LIBCPP_NODEBUG = array;
|
|
|
|
using value_type = _Tp;
|
|
|
|
using reference = value_type&;
|
|
|
|
using const_reference = const value_type&;
|
|
|
|
using pointer = value_type*;
|
|
|
|
using const_pointer = const value_type*;
|
2024-12-10 16:02:12 +01:00
|
|
|
# if defined(_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY)
|
2024-11-07 09:23:21 -05:00
|
|
|
using iterator = __static_bounded_iter<pointer, _Size>;
|
|
|
|
using const_iterator = __static_bounded_iter<const_pointer, _Size>;
|
2024-12-10 16:02:12 +01:00
|
|
|
# elif defined(_LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY)
|
2024-03-04 18:23:53 -05:00
|
|
|
using iterator = __wrap_iter<pointer>;
|
|
|
|
using const_iterator = __wrap_iter<const_pointer>;
|
2024-12-10 16:02:12 +01:00
|
|
|
# else
|
2024-03-04 18:23:53 -05:00
|
|
|
using iterator = pointer;
|
|
|
|
using const_iterator = const_pointer;
|
2024-12-10 16:02:12 +01:00
|
|
|
# endif
|
2023-12-05 11:21:06 -05:00
|
|
|
using size_type = size_t;
|
|
|
|
using difference_type = ptrdiff_t;
|
|
|
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
|
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2018-02-07 21:06:13 +00:00
|
|
|
_Tp __elems_[_Size];
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
// No explicit construct/copy/destroy for aggregate type
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void fill(const value_type& __u) {
|
2020-06-01 16:28:44 -04:00
|
|
|
std::fill_n(data(), _Size, __u);
|
2018-02-07 21:06:13 +00:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2024-06-18 11:01:43 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(array& __a) _NOEXCEPT_(__is_nothrow_swappable_v<_Tp>) {
|
[libc++] Consistently replace `std::` qualification with `_VSTD::` or nothing. NFCI.
I used a lot of `git grep` to find places where `std::` was being used
outside of comments and assert-messages. There were three outcomes:
- Qualified function calls, e.g. `std::move` becomes `_VSTD::move`.
This is the most common case.
- Typenames that don't need qualification, e.g. `std::allocator` becomes `allocator`.
Leaving these as `_VSTD::allocator` would also be fine, but I decided
that removing the qualification is more consistent with existing practice.
- Names that specifically need un-versioned `std::` qualification,
or that I wasn't sure about. For example, I didn't touch any code in
<atomic>, <math.h>, <new>, or any ext/ or experimental/ headers;
and I didn't touch any instances of `std::type_info`.
In some deduction guides, we were accidentally using `class Alloc = typename std::allocator<T>`,
despite `std::allocator<T>`'s type-ness not being template-dependent.
Because `std::allocator` is a qualified name, this did parse as we intended;
but what we meant was simply `class Alloc = allocator<T>`.
Differential Revision: https://reviews.llvm.org/D92250
2020-11-27 11:02:06 -05:00
|
|
|
std::swap_ranges(data(), data() + _Size, __a.data());
|
2018-02-07 21:06:13 +00:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
// iterators:
|
2024-11-07 09:23:21 -05:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 iterator begin() _NOEXCEPT {
|
2024-12-10 16:02:12 +01:00
|
|
|
# if defined(_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY)
|
2024-11-07 09:23:21 -05:00
|
|
|
return std::__make_static_bounded_iter<_Size>(data(), data());
|
2024-12-10 16:02:12 +01:00
|
|
|
# else
|
2024-11-07 09:23:21 -05:00
|
|
|
return iterator(data());
|
2024-12-10 16:02:12 +01:00
|
|
|
# endif
|
2024-11-07 09:23:21 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const_iterator begin() const _NOEXCEPT {
|
2024-12-10 16:02:12 +01:00
|
|
|
# if defined(_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY)
|
2024-11-07 09:23:21 -05:00
|
|
|
return std::__make_static_bounded_iter<_Size>(data(), data());
|
2024-12-10 16:02:12 +01:00
|
|
|
# else
|
2018-02-07 21:06:13 +00:00
|
|
|
return const_iterator(data());
|
2024-12-10 16:02:12 +01:00
|
|
|
# endif
|
2024-11-07 09:23:21 -05:00
|
|
|
}
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 iterator end() _NOEXCEPT {
|
2024-12-10 16:02:12 +01:00
|
|
|
# if defined(_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY)
|
2024-11-07 09:23:21 -05:00
|
|
|
return std::__make_static_bounded_iter<_Size>(data() + _Size, data());
|
2024-12-10 16:02:12 +01:00
|
|
|
# else
|
2024-11-07 09:23:21 -05:00
|
|
|
return iterator(data() + _Size);
|
2024-12-10 16:02:12 +01:00
|
|
|
# endif
|
2018-02-07 21:06:13 +00:00
|
|
|
}
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const_iterator end() const _NOEXCEPT {
|
2024-12-10 16:02:12 +01:00
|
|
|
# if defined(_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY)
|
2024-11-07 09:23:21 -05:00
|
|
|
return std::__make_static_bounded_iter<_Size>(data() + _Size, data());
|
2024-12-10 16:02:12 +01:00
|
|
|
# else
|
2018-02-07 21:06:13 +00:00
|
|
|
return const_iterator(data() + _Size);
|
2024-12-10 16:02:12 +01:00
|
|
|
# endif
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reverse_iterator rbegin() _NOEXCEPT {
|
2011-05-31 21:06:33 +00:00
|
|
|
return reverse_iterator(end());
|
|
|
|
}
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const_reverse_iterator rbegin() const _NOEXCEPT {
|
|
|
|
return const_reverse_iterator(end());
|
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reverse_iterator rend() _NOEXCEPT {
|
2011-05-31 21:06:33 +00:00
|
|
|
return reverse_iterator(begin());
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2011-05-31 21:06:33 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const_reverse_iterator rend() const _NOEXCEPT {
|
|
|
|
return const_reverse_iterator(begin());
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
|
|
|
|
2018-02-07 21:06:13 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const_iterator cbegin() const _NOEXCEPT { return begin(); }
|
2011-05-31 21:06:33 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const_iterator cend() const _NOEXCEPT { return end(); }
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const_reverse_iterator crbegin() const _NOEXCEPT {
|
2018-02-07 21:06:13 +00:00
|
|
|
return rbegin();
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2011-05-31 21:06:33 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const_reverse_iterator crend() const _NOEXCEPT { return rend(); }
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
// capacity:
|
2012-07-20 19:20:49 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR size_type size() const _NOEXCEPT { return _Size; }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR size_type max_size() const _NOEXCEPT { return _Size; }
|
2024-09-12 21:18:43 +02:00
|
|
|
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT { return _Size == 0; }
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
// element access:
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference operator[](size_type __n) _NOEXCEPT {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < _Size, "out-of-bounds access in std::array<T, N>");
|
2020-06-01 16:35:42 -04:00
|
|
|
return __elems_[__n];
|
|
|
|
}
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const_reference operator[](size_type __n) const _NOEXCEPT {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__n < _Size, "out-of-bounds access in std::array<T, N>");
|
2020-06-01 16:35:42 -04:00
|
|
|
return __elems_[__n];
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2023-01-23 10:27:14 +01:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference at(size_type __n) {
|
2020-05-22 09:23:32 -04:00
|
|
|
if (__n >= _Size)
|
2025-02-21 07:59:46 -05:00
|
|
|
std::__throw_out_of_range("array::at");
|
2020-05-22 09:23:32 -04:00
|
|
|
return __elems_[__n];
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2023-01-23 10:27:14 +01:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const_reference at(size_type __n) const {
|
2020-05-22 09:23:32 -04:00
|
|
|
if (__n >= _Size)
|
2025-02-21 07:59:46 -05:00
|
|
|
std::__throw_out_of_range("array::at");
|
2020-05-22 09:23:32 -04:00
|
|
|
return __elems_[__n];
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference front() _NOEXCEPT { return (*this)[0]; }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const_reference front() const _NOEXCEPT { return (*this)[0]; }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference back() _NOEXCEPT { return (*this)[_Size - 1]; }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const_reference back() const _NOEXCEPT {
|
|
|
|
return (*this)[_Size - 1];
|
2018-02-06 03:03:37 +00:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 value_type* data() _NOEXCEPT { return __elems_; }
|
2018-02-06 03:03:37 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const value_type* data() const _NOEXCEPT { return __elems_; }
|
2010-05-11 19:42:16 +00:00
|
|
|
};
|
|
|
|
|
2018-02-07 21:06:13 +00:00
|
|
|
template <class _Tp>
|
2025-04-09 23:47:57 +02:00
|
|
|
struct array<_Tp, 0> {
|
2018-02-07 21:06:13 +00:00
|
|
|
// types:
|
2025-01-08 17:12:59 +01:00
|
|
|
using __self _LIBCPP_NODEBUG = array;
|
|
|
|
using value_type = _Tp;
|
|
|
|
using reference = value_type&;
|
|
|
|
using const_reference = const value_type&;
|
|
|
|
using pointer = value_type*;
|
|
|
|
using const_pointer = const value_type*;
|
2024-12-10 16:02:12 +01:00
|
|
|
# if defined(_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY)
|
2024-11-07 09:23:21 -05:00
|
|
|
using iterator = __static_bounded_iter<pointer, 0>;
|
|
|
|
using const_iterator = __static_bounded_iter<const_pointer, 0>;
|
2024-12-10 16:02:12 +01:00
|
|
|
# elif defined(_LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY)
|
2024-07-30 20:24:11 +02:00
|
|
|
using iterator = __wrap_iter<pointer>;
|
|
|
|
using const_iterator = __wrap_iter<const_pointer>;
|
2024-12-10 16:02:12 +01:00
|
|
|
# else
|
2024-07-30 20:24:11 +02:00
|
|
|
using iterator = pointer;
|
|
|
|
using const_iterator = const_pointer;
|
2024-12-10 16:02:12 +01:00
|
|
|
# endif
|
2024-07-30 20:24:11 +02:00
|
|
|
using size_type = size_t;
|
|
|
|
using difference_type = ptrdiff_t;
|
|
|
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
|
|
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
|
|
|
|
2025-01-08 17:12:59 +01:00
|
|
|
using _EmptyType _LIBCPP_NODEBUG = __conditional_t<is_const<_Tp>::value, const __empty, __empty>;
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2018-02-07 23:50:25 +00:00
|
|
|
struct _ArrayInStructT {
|
|
|
|
_Tp __data_[1];
|
|
|
|
};
|
2023-12-15 16:06:12 -05:00
|
|
|
_ALIGNAS_TYPE(_ArrayInStructT) _EmptyType __elems_[sizeof(_ArrayInStructT)];
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 value_type* data() _NOEXCEPT { return nullptr; }
|
[libc++] Fix issues with the triviality of std::array
The Standard is currently unimplementable. We have to pick between:
1. Not implementing constexpr support properly in std::array<T, 0>
2. Making std::array<T, 0> non-trivial even when T is trivial
3. Returning nullptr from std::array<T, 0>::begin()
Libc++ initially picked (1). In 77b9abfc8e89, we started implementing constexpr properly, but lost the guarantee of triviality. Since it seems like both (1) and (2) are really important, it seems like (3) is the only viable option for libc++, after all. This is also what other implementations are doing.
This patch moves libc++ from (1) to (3).
It also:
- Improves the test coverage for the various ways of initializing std::array
- Adds tests for the triviality of std::array
- Adds tests for the aggregate-ness of std::array
Reviewed By: #libc, miscco, EricWF, zoecarver
Differential Revision: https://reviews.llvm.org/D80821
2020-05-29 16:32:55 -07:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const value_type* data() const _NOEXCEPT { return nullptr; }
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2018-02-07 21:06:13 +00:00
|
|
|
// No explicit construct/copy/destroy for aggregate type
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void fill(const value_type&) {
|
2018-02-07 21:06:13 +00:00
|
|
|
static_assert(!is_const<_Tp>::value, "cannot fill zero-sized array of type 'const T'");
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(array&) _NOEXCEPT {
|
2018-02-07 21:06:13 +00:00
|
|
|
static_assert(!is_const<_Tp>::value, "cannot swap zero-sized array of type 'const T'");
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2018-02-07 21:06:13 +00:00
|
|
|
// iterators:
|
2024-11-07 09:23:21 -05:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 iterator begin() _NOEXCEPT {
|
2024-12-10 16:02:12 +01:00
|
|
|
# if defined(_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY)
|
2024-11-07 09:23:21 -05:00
|
|
|
return std::__make_static_bounded_iter<0>(data(), data());
|
2024-12-10 16:02:12 +01:00
|
|
|
# else
|
2024-11-07 09:23:21 -05:00
|
|
|
return iterator(data());
|
2024-12-10 16:02:12 +01:00
|
|
|
# endif
|
2024-11-07 09:23:21 -05:00
|
|
|
}
|
2018-02-07 21:06:13 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const_iterator begin() const _NOEXCEPT {
|
2024-12-10 16:02:12 +01:00
|
|
|
# if defined(_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY)
|
2024-11-07 09:23:21 -05:00
|
|
|
return std::__make_static_bounded_iter<0>(data(), data());
|
2024-12-10 16:02:12 +01:00
|
|
|
# else
|
2018-02-07 21:06:13 +00:00
|
|
|
return const_iterator(data());
|
2024-12-10 16:02:12 +01:00
|
|
|
# endif
|
2024-11-07 09:23:21 -05:00
|
|
|
}
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 iterator end() _NOEXCEPT {
|
2024-12-10 16:02:12 +01:00
|
|
|
# if defined(_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY)
|
2024-11-07 09:23:21 -05:00
|
|
|
return std::__make_static_bounded_iter<0>(data(), data());
|
2024-12-10 16:02:12 +01:00
|
|
|
# else
|
2024-11-07 09:23:21 -05:00
|
|
|
return iterator(data());
|
2024-12-10 16:02:12 +01:00
|
|
|
# endif
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const_iterator end() const _NOEXCEPT {
|
2024-12-10 16:02:12 +01:00
|
|
|
# if defined(_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY)
|
2024-11-07 09:23:21 -05:00
|
|
|
return std::__make_static_bounded_iter<0>(data(), data());
|
2024-12-10 16:02:12 +01:00
|
|
|
# else
|
2018-02-07 21:06:13 +00:00
|
|
|
return const_iterator(data());
|
2024-12-10 16:02:12 +01:00
|
|
|
# endif
|
2018-02-07 21:06:13 +00:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reverse_iterator rbegin() _NOEXCEPT {
|
2018-02-07 21:06:13 +00:00
|
|
|
return reverse_iterator(end());
|
|
|
|
}
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const_reverse_iterator rbegin() const _NOEXCEPT {
|
|
|
|
return const_reverse_iterator(end());
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reverse_iterator rend() _NOEXCEPT {
|
2011-05-31 21:06:33 +00:00
|
|
|
return reverse_iterator(begin());
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const_reverse_iterator rend() const _NOEXCEPT {
|
2018-02-07 21:06:13 +00:00
|
|
|
return const_reverse_iterator(begin());
|
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const_iterator cbegin() const _NOEXCEPT { return begin(); }
|
2018-02-07 21:06:13 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const_iterator cend() const _NOEXCEPT { return end(); }
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const_reverse_iterator crbegin() const _NOEXCEPT {
|
2018-02-07 21:06:13 +00:00
|
|
|
return rbegin();
|
2023-12-18 14:01:33 -05:00
|
|
|
}
|
2018-02-07 21:06:13 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 const_reverse_iterator crend() const _NOEXCEPT { return rend(); }
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2018-02-07 21:06:13 +00:00
|
|
|
// capacity:
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR size_type size() const _NOEXCEPT { return 0; }
|
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR size_type max_size() const _NOEXCEPT { return 0; }
|
2024-09-12 21:18:43 +02:00
|
|
|
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT { return true; }
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2018-02-07 21:06:13 +00:00
|
|
|
// element access:
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference operator[](size_type) _NOEXCEPT {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "cannot call array<T, 0>::operator[] on a zero-sized array");
|
2022-02-14 18:26:02 +01:00
|
|
|
__libcpp_unreachable();
|
2018-02-07 21:06:13 +00:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2019-03-14 21:56:57 +00:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const_reference operator[](size_type) const _NOEXCEPT {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "cannot call array<T, 0>::operator[] on a zero-sized array");
|
2022-02-14 18:26:02 +01:00
|
|
|
__libcpp_unreachable();
|
2018-02-07 21:06:13 +00:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference at(size_type) {
|
2025-02-21 07:59:46 -05:00
|
|
|
std::__throw_out_of_range("array<T, 0>::at");
|
2022-02-14 18:26:02 +01:00
|
|
|
__libcpp_unreachable();
|
2018-02-07 21:06:13 +00:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const_reference at(size_type) const {
|
2025-02-21 07:59:46 -05:00
|
|
|
std::__throw_out_of_range("array<T, 0>::at");
|
2022-02-14 18:26:02 +01:00
|
|
|
__libcpp_unreachable();
|
2018-02-07 21:06:13 +00:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference front() _NOEXCEPT {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "cannot call array<T, 0>::front() on a zero-sized array");
|
2022-02-14 18:26:02 +01:00
|
|
|
__libcpp_unreachable();
|
2018-02-07 21:06:13 +00:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const_reference front() const _NOEXCEPT {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "cannot call array<T, 0>::front() on a zero-sized array");
|
2022-02-14 18:26:02 +01:00
|
|
|
__libcpp_unreachable();
|
2018-02-07 21:06:13 +00:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 reference back() _NOEXCEPT {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "cannot call array<T, 0>::back() on a zero-sized array");
|
2022-02-14 18:26:02 +01:00
|
|
|
__libcpp_unreachable();
|
2018-02-07 21:06:13 +00:00
|
|
|
}
|
2023-12-18 14:01:33 -05:00
|
|
|
|
2022-08-19 13:08:01 +02:00
|
|
|
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const_reference back() const _NOEXCEPT {
|
2023-07-20 10:13:54 -07:00
|
|
|
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(false, "cannot call array<T, 0>::back() on a zero-sized array");
|
2022-02-14 18:26:02 +01:00
|
|
|
__libcpp_unreachable();
|
2018-02-07 21:06:13 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2024-12-10 16:02:12 +01:00
|
|
|
# if _LIBCPP_STD_VER >= 17
|
[libc++] Use enable_if_t instead of _EnableIf
I just ran into a compiler error involving __bind_back and some overloads
that were being disabled with _EnableIf. I noticed that the error message
was quite bad and did not mention the reason for the overload being
excluded. Specifically, the error looked like this:
candidate template ignored: substitution failure [with _Args =
<ContiguousView>]: no member named '_EnableIfImpl' in 'std::_MetaBase<false>'
Instead, when using enable_if or enable_if_t, the compiler is clever and
can produce better diagnostics, like so:
candidate template ignored: requirement 'is_invocable_v<
std::__bind_back_op<1, std::integer_sequence<unsigned long, 0>>,
std::ranges::views::__transform::__fn &, std::tuple<PlusOne> &,
ContiguousView>' was not satisfied [with _Args = <ContiguousView>]
Basically, it tries to do a poor man's implementation of concepts, which
is already a lot better than simply complaining about substitution failure.
Hence, this commit uses enable_if_t instead of _EnableIf whenever
possible. That is both more straightforward than using the internal
helper, and also leads to better error messages in those cases.
I understand the motivation for _EnableIf's implementation was to improve
compile-time performance, however I believe striving to improve error
messages is even more important for our QOI, hence this patch. Furthermore,
it is unclear that _EnableIf actually improved compile-time performance
in any noticeable way (see discussion in the review for details).
Differential Revision: https://reviews.llvm.org/D108216
2021-08-17 12:26:09 -04:00
|
|
|
template <class _Tp, class... _Args, class = enable_if_t<__all<_IsSame<_Tp, _Args>::value...>::value> >
|
2018-05-18 21:01:04 +00:00
|
|
|
array(_Tp, _Args...) -> array<_Tp, 1 + sizeof...(_Args)>;
|
2024-12-10 16:02:12 +01:00
|
|
|
# endif
|
2018-05-18 21:01:04 +00:00
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Tp, size_t _Size>
|
2022-08-19 13:08:01 +02:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
|
2010-05-11 19:42:16 +00:00
|
|
|
operator==(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) {
|
2018-02-07 21:06:13 +00:00
|
|
|
return std::equal(__x.begin(), __x.end(), __y.begin());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2024-12-10 16:02:12 +01:00
|
|
|
# if _LIBCPP_STD_VER <= 17
|
2023-05-06 15:41:41 +03:00
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Tp, size_t _Size>
|
2023-05-06 15:41:41 +03:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) {
|
2010-05-11 19:42:16 +00:00
|
|
|
return !(__x == __y);
|
|
|
|
}
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Tp, size_t _Size>
|
2023-05-06 15:41:41 +03:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI bool operator<(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) {
|
|
|
|
return std::lexicographical_compare(__x.begin(), __x.end(), __y.begin(), __y.end());
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Tp, size_t _Size>
|
2023-05-06 15:41:41 +03:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI bool operator>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) {
|
2010-05-11 19:42:16 +00:00
|
|
|
return __y < __x;
|
|
|
|
}
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Tp, size_t _Size>
|
2023-05-06 15:41:41 +03:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) {
|
2010-05-11 19:42:16 +00:00
|
|
|
return !(__y < __x);
|
|
|
|
}
|
|
|
|
|
2010-08-22 00:02:43 +00:00
|
|
|
template <class _Tp, size_t _Size>
|
2023-05-06 15:41:41 +03:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI bool operator>=(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) {
|
2010-05-11 19:42:16 +00:00
|
|
|
return !(__x < __y);
|
|
|
|
}
|
|
|
|
|
2024-12-10 16:02:12 +01:00
|
|
|
# else // _LIBCPP_STD_VER <= 17
|
2023-05-06 15:41:41 +03:00
|
|
|
|
|
|
|
template <class _Tp, size_t _Size>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr __synth_three_way_result<_Tp>
|
|
|
|
operator<=>(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y) {
|
2024-08-30 12:07:07 -04:00
|
|
|
return std::lexicographical_compare_three_way(__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
|
2023-05-06 15:41:41 +03:00
|
|
|
}
|
|
|
|
|
2024-12-10 16:02:12 +01:00
|
|
|
# endif // _LIBCPP_STD_VER <= 17
|
2023-05-06 15:41:41 +03:00
|
|
|
|
2024-06-18 11:01:43 +02:00
|
|
|
template <class _Tp, size_t _Size, __enable_if_t<_Size == 0 || __is_swappable_v<_Tp>, int> = 0>
|
2022-08-19 13:08:01 +02:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void swap(array<_Tp, _Size>& __x, array<_Tp, _Size>& __y)
|
2016-04-21 23:38:59 +00:00
|
|
|
_NOEXCEPT_(noexcept(__x.swap(__y))) {
|
2010-05-11 19:42:16 +00:00
|
|
|
__x.swap(__y);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class _Tp, size_t _Size>
|
2025-04-09 23:47:57 +02:00
|
|
|
struct tuple_size<array<_Tp, _Size> > : public integral_constant<size_t, _Size> {};
|
2010-05-11 19:42:16 +00:00
|
|
|
|
|
|
|
template <size_t _Ip, class _Tp, size_t _Size>
|
2025-04-09 23:47:57 +02:00
|
|
|
struct tuple_element<_Ip, array<_Tp, _Size> > {
|
2017-06-12 14:41:37 +00:00
|
|
|
static_assert(_Ip < _Size, "Index out of bounds in std::tuple_element<> (std::array)");
|
2025-03-23 21:01:25 +01:00
|
|
|
using type _LIBCPP_NODEBUG = _Tp;
|
2010-05-11 19:42:16 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
template <size_t _Ip, class _Tp, size_t _Size>
|
2022-08-19 13:08:01 +02:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp& get(array<_Tp, _Size>& __a) _NOEXCEPT {
|
2012-12-18 16:46:30 +00:00
|
|
|
static_assert(_Ip < _Size, "Index out of bounds in std::get<> (std::array)");
|
2013-07-17 18:25:36 +00:00
|
|
|
return __a.__elems_[_Ip];
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <size_t _Ip, class _Tp, size_t _Size>
|
2022-08-19 13:08:01 +02:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp& get(const array<_Tp, _Size>& __a) _NOEXCEPT {
|
2012-12-18 16:46:30 +00:00
|
|
|
static_assert(_Ip < _Size, "Index out of bounds in std::get<> (const std::array)");
|
2013-07-17 18:25:36 +00:00
|
|
|
return __a.__elems_[_Ip];
|
2010-05-11 19:42:16 +00:00
|
|
|
}
|
|
|
|
|
2010-11-17 19:52:17 +00:00
|
|
|
template <size_t _Ip, class _Tp, size_t _Size>
|
2022-08-19 13:08:01 +02:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp&& get(array<_Tp, _Size>&& __a) _NOEXCEPT {
|
2012-12-18 16:46:30 +00:00
|
|
|
static_assert(_Ip < _Size, "Index out of bounds in std::get<> (std::array &&)");
|
2013-07-17 18:25:36 +00:00
|
|
|
return std::move(__a.__elems_[_Ip]);
|
2010-11-17 19:52:17 +00:00
|
|
|
}
|
|
|
|
|
2015-12-18 00:36:55 +00:00
|
|
|
template <size_t _Ip, class _Tp, size_t _Size>
|
2022-08-19 13:08:01 +02:00
|
|
|
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp&& get(const array<_Tp, _Size>&& __a) _NOEXCEPT {
|
2015-12-18 00:36:55 +00:00
|
|
|
static_assert(_Ip < _Size, "Index out of bounds in std::get<> (const std::array &&)");
|
|
|
|
return std::move(__a.__elems_[_Ip]);
|
|
|
|
}
|
|
|
|
|
2024-12-10 16:02:12 +01:00
|
|
|
# if _LIBCPP_STD_VER >= 20
|
2020-01-30 13:27:35 +01:00
|
|
|
|
|
|
|
template <typename _Tp, size_t _Size, size_t... _Index>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr array<remove_cv_t<_Tp>, _Size>
|
|
|
|
__to_array_lvalue_impl(_Tp (&__arr)[_Size], index_sequence<_Index...>) {
|
|
|
|
return {{__arr[_Index]...}};
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename _Tp, size_t _Size, size_t... _Index>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr array<remove_cv_t<_Tp>, _Size>
|
|
|
|
__to_array_rvalue_impl(_Tp (&&__arr)[_Size], index_sequence<_Index...>) {
|
|
|
|
return {{std::move(__arr[_Index])...}};
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename _Tp, size_t _Size>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr array<remove_cv_t<_Tp>, _Size>
|
|
|
|
to_array(_Tp (&__arr)[_Size]) noexcept(is_nothrow_constructible_v<_Tp, _Tp&>) {
|
|
|
|
static_assert(!is_array_v<_Tp>, "[array.creation]/1: to_array does not accept multidimensional arrays.");
|
|
|
|
static_assert(is_constructible_v<_Tp, _Tp&>, "[array.creation]/1: to_array requires copy constructible elements.");
|
2020-12-15 19:32:29 -05:00
|
|
|
return std::__to_array_lvalue_impl(__arr, make_index_sequence<_Size>());
|
2020-01-30 13:27:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
template <typename _Tp, size_t _Size>
|
|
|
|
_LIBCPP_HIDE_FROM_ABI constexpr array<remove_cv_t<_Tp>, _Size>
|
|
|
|
to_array(_Tp (&&__arr)[_Size]) noexcept(is_nothrow_move_constructible_v<_Tp>) {
|
|
|
|
static_assert(!is_array_v<_Tp>, "[array.creation]/4: to_array does not accept multidimensional arrays.");
|
|
|
|
static_assert(is_move_constructible_v<_Tp>, "[array.creation]/4: to_array requires move constructible elements.");
|
2020-12-15 19:32:29 -05:00
|
|
|
return std::__to_array_rvalue_impl(std::move(__arr), make_index_sequence<_Size>());
|
2020-01-30 13:27:35 +01:00
|
|
|
}
|
|
|
|
|
2024-12-10 16:02:12 +01:00
|
|
|
# endif // _LIBCPP_STD_VER >= 20
|
2020-01-30 13:27:35 +01:00
|
|
|
|
2010-05-11 19:42:16 +00:00
|
|
|
_LIBCPP_END_NAMESPACE_STD
|
|
|
|
|
[libc++] Fix missing and incorrect push/pop macros (#79204)
We recently noticed that the unwrap_iter.h file was pushing macros, but
it was pushing them again instead of popping them at the end of the
file. This led to libc++ basically swallowing any custom definition of
these macros in user code:
#define min HELLO
#include <algorithm>
// min is not HELLO anymore, it's not defined
While investigating this issue, I noticed that our push/pop pragmas were
actually entirely wrong too. Indeed, instead of pushing macros like
`move`, we'd push `move(int, int)` in the pragma, which is not a valid
macro name. As a result, we would not actually push macros like `move`
-- instead we'd simply undefine them. This led to the following code not
working:
#define move HELLO
#include <algorithm>
// move is not HELLO anymore
Fixing the pragma push/pop incantations led to a cascade of issues
because we use identifiers like `move` in a large number of places, and
all of these headers would now need to do the push/pop dance.
This patch fixes all these issues. First, it adds a check that we don't
swallow important names like min, max, move or refresh as explained
above. This is done by augmenting the existing
system_reserved_names.gen.py test to also check that the macros are what
we expect after including each header.
Second, it fixes the push/pop pragmas to work properly and adds missing
pragmas to all the files I could detect a failure in via the newly added
test.
rdar://121365472
2024-01-25 15:48:46 -05:00
|
|
|
_LIBCPP_POP_MACROS
|
|
|
|
|
2024-12-10 16:02:12 +01:00
|
|
|
# if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
|
|
|
|
# include <algorithm>
|
|
|
|
# include <concepts>
|
|
|
|
# include <cstdlib>
|
|
|
|
# include <iterator>
|
2024-12-13 14:17:56 -05:00
|
|
|
# include <new>
|
2024-12-10 16:02:12 +01:00
|
|
|
# include <type_traits>
|
|
|
|
# include <utility>
|
|
|
|
# endif
|
2024-12-21 13:01:48 +01:00
|
|
|
#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
|
2022-09-02 17:53:28 +02:00
|
|
|
|
2021-04-20 12:03:32 -04:00
|
|
|
#endif // _LIBCPP_ARRAY
|