73 using const_pointer = T
const*;
77 using const_reference = T
const&;
79 using size_type = std::size_t;
81 using difference_type = std::ptrdiff_t;
84 using iterator =
typename span<T, N>::iterator;
86 using const_iterator =
typename span<T
const, N>::iterator;
89 using reverse_iterator =
typename span<T, N>::reverse_iterator;
91 using const_reverse_iterator =
typename span<T, N>::const_reverse_iterator;
97 static constexpr std::integral_constant<std::size_t, N> size{};
107 static constexpr std::integral_constant<std::size_t, N> max_size{};
116 static constexpr std::integral_constant<
bool,
false> empty{};
122 constexpr auto data()
noexcept -> T* {
return values_; }
126 constexpr auto data()
const noexcept -> T
const* {
return values_; }
130 constexpr auto begin()
noexcept -> iterator {
return span<T, N>{values_}.begin(); }
134 constexpr auto end()
noexcept -> iterator {
return span<T, N>{values_}.end(); }
138 constexpr auto begin()
const noexcept -> const_iterator {
return span<T
const, N>{values_}.begin(); }
142 constexpr auto end()
const noexcept -> const_iterator {
return span<T
const, N>{values_}.end(); }
146 constexpr auto rbegin()
noexcept -> reverse_iterator {
return span<T, N>{values_}.rbegin(); }
150 constexpr auto rend()
noexcept -> reverse_iterator {
return span<T, N>{values_}.rend(); }
154 constexpr auto rbegin()
const noexcept -> const_reverse_iterator {
return span<T
const, N>{values_}.rbegin(); }
158 constexpr auto rend()
const noexcept -> const_reverse_iterator {
return span<T
const, N>{values_}.rend(); }
162 constexpr auto cbegin()
const noexcept -> const_iterator {
return span<T
const, N>{values_}.begin(); }
166 constexpr auto cend()
const noexcept -> const_iterator {
return span<T
const, N>{values_}.end(); }
170 constexpr auto crbegin()
const noexcept -> const_reverse_iterator {
return span<T
const, N>{values_}.rbegin(); }
174 constexpr auto crend()
const noexcept -> const_reverse_iterator {
return span<T
const, N>{values_}.rend(); }
181 constexpr auto operator[](std::size_t index)
noexcept -> T& {
182 ARENE_PRECONDITION(index < size());
183 return values_[index];
190 constexpr auto operator[](std::size_t index)
const noexcept -> T
const& {
191 ARENE_PRECONDITION(index < size());
192 return values_[index];
203 bool AreExceptionsEnabled = detail::are_exceptions_enabled::value,
204 constraints<std::enable_if_t<AreExceptionsEnabled>> =
nullptr>
205 constexpr auto at(std::size_t index) -> T& {
206 if (index >= size()) {
207 array_detail::throw_out_of_range();
209 return values_[index];
219 bool AreExceptionsEnabled = detail::are_exceptions_enabled::value,
220 constraints<std::enable_if_t<AreExceptionsEnabled>> =
nullptr>
221 constexpr auto at(std::size_t index)
const -> T
const& {
222 if (index >= size()) {
223 array_detail::throw_out_of_range();
225 return values_[index];
231 constexpr auto front()
noexcept -> T& {
return (*
this)[0]; }
236 constexpr auto front()
const noexcept -> T
const& {
return (*
this)[0]; }
241 constexpr auto back()
noexcept -> T& {
return (*
this)[N - 1U]; }
246 constexpr auto back()
const noexcept -> T
const& {
return (*
this)[N - 1U]; }
259 template <
typename U = T, constraints<std::enable_if_t<is_equality_comparable_v<U>>> =
nullptr>
260 friend constexpr auto operator==(array
const& lhs, array
const& rhs)
noexcept ->
bool {
261 return arene::base::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
263 template <std::size_t UN,
typename U = T, constraints<std::enable_if_t<is_equality_comparable_v<U>>> =
nullptr>
264 friend constexpr auto operator==(array
const&, array<T, UN>
const&)
noexcept ->
bool {
270 std::enable_if_t<!is_equality_comparable_v<U>>,
271 std::enable_if_t<compare_three_way_supported_v<U>>,
272 std::enable_if_t<!has_fast_inequality_check_v<U>>> =
nullptr>
273 friend constexpr auto operator==(array
const& lhs, array
const& rhs)
noexcept ->
bool {
274 return array::three_way_compare(lhs, rhs) == arene::base::strong_ordering::equal;
279 std::enable_if_t<!is_equality_comparable_v<U>>,
280 std::enable_if_t<compare_three_way_supported_v<U>>,
281 std::enable_if_t<has_fast_inequality_check_v<U>>> =
nullptr>
282 friend constexpr auto operator==(array
const& lhs, array
const& rhs)
noexcept ->
bool {
283 return (array::fast_inequality_check(lhs, rhs) == inequality_heuristic::may_be_equal_or_not_equal) &&
284 (array::three_way_compare(lhs, rhs) == arene::base::strong_ordering::equal);
289 constraints<std::enable_if_t<!is_equality_comparable_v<U>>, std::enable_if_t<compare_three_way_supported_v<U>>> =
291 friend constexpr auto operator==(array
const&, array<T, UN>
const&)
noexcept ->
bool {
309 template <std::size_t UN,
typename U = T>
310 friend constexpr auto operator!=(array
const& lhs, array<T, UN>
const& rhs)
noexcept ->
bool {
311 return !(lhs == rhs);
331 template <std::size_t UN,
typename U = T, constraints<std::enable_if_t<compare_three_way_supported_v<U>>> =
nullptr>
332 static constexpr auto three_way_compare(array
const& lhs, array<T, UN>
const& rhs)
noexcept
333 -> arene::base::strong_ordering {
334 return lexicographical_compare_three_way(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
336 template <
typename U = T, constraints<std::enable_if_t<compare_three_way_supported_v<U>>> =
nullptr>
337 static constexpr auto three_way_compare(array
const&, array<T, 0>
const&)
noexcept -> arene::base::strong_ordering {
340 return arene::base::strong_ordering::greater;
355 template <std::size_t UN,
typename U = T, constraints<std::enable_if_t<has_fast_inequality_check_v<U>>> =
nullptr>
356 static constexpr auto fast_inequality_check(array
const& lhs, array<T, UN>
const& rhs)
noexcept
357 -> arene::base::inequality_heuristic {
358 if (size() != rhs.size()) {
359 return arene::base::inequality_heuristic::definitely_not_equal;
362 for (size_type idx{}; idx < size(); ++idx) {
363 if (U::fast_inequality_check(lhs[idx], rhs[idx]) == arene::base::inequality_heuristic::definitely_not_equal) {
364 return arene::base::inequality_heuristic::definitely_not_equal;
368 return arene::base::inequality_heuristic::may_be_equal_or_not_equal;
381 template <std::size_t UN>
382 friend constexpr auto operator<(array
const& lhs, array<T, UN>
const& rhs)
noexcept ->
bool {
383 return array::three_way_compare(lhs, rhs) == arene::base::strong_ordering::less;
385 template <std::size_t UN>
386 friend constexpr auto operator<=(array
const& lhs, array<T, UN>
const& rhs)
noexcept ->
bool {
387 return array::three_way_compare(lhs, rhs) != arene::base::strong_ordering::greater;
389 template <std::size_t UN>
390 friend constexpr auto operator>(array
const& lhs, array<T, UN>
const& rhs)
noexcept ->
bool {
391 return array::three_way_compare(lhs, rhs) == arene::base::strong_ordering::greater;
393 template <std::size_t UN>
394 friend constexpr auto operator>=(array
const& lhs, array<T, UN>
const& rhs)
noexcept ->
bool {
395 return array::three_way_compare(lhs, rhs) != arene::base::strong_ordering::less;
407 constraints<std::enable_if_t<std::is_same<U, T>::value>, std::enable_if_t<std::is_copy_assignable<U>::value>> =
409 constexpr void fill(T
const& val)
noexcept(std::is_nothrow_copy_assignable<T>::value) {
411 for (T& elem : values_) {
427 constraints<std::enable_if_t<std::is_same<U, T>::value>, std::enable_if_t<is_swappable_v<U>>> =
nullptr>
428 constexpr void swap(array& other)
noexcept(is_nothrow_swappable_v<U>) {
429 iterator rhs_iter{other.begin()};
430 for (
auto& lhs_elem : *
this) {
431 ::arene::base::swap(lhs_elem, *rhs_iter);
448 constraints<std::enable_if_t<std::is_same<U, T>::value>, std::enable_if_t<is_swappable_v<U>>> =
nullptr>
449 friend constexpr void swap(array& lhs, array& rhs)
noexcept(
noexcept(lhs.swap(rhs))) {
487 using value_type = T;
491 using const_pointer = T
const*;
493 using reference = T&;
495 using const_reference = T
const&;
497 using size_type = std::size_t;
499 using difference_type = std::ptrdiff_t;
502 using iterator =
typename span<T, 0>::iterator;
504 using const_iterator =
typename span<T
const, 0>::iterator;
507 using reverse_iterator =
typename span<T, 0>::reverse_iterator;
509 using const_reverse_iterator =
typename span<T, 0>::const_reverse_iterator;
515 static constexpr std::integral_constant<std::size_t, 0> size{};
522 static constexpr std::integral_constant<std::size_t, 0> max_size{};
529 static constexpr std::integral_constant<
bool,
true> empty{};
535 constexpr auto data()
noexcept -> T* {
return nullptr; }
541 constexpr auto data()
const noexcept -> T
const* {
return nullptr; }
547 constexpr auto begin()
noexcept -> iterator {
return {}; }
553 constexpr auto end()
noexcept -> iterator {
return {}; }
559 constexpr auto begin()
const noexcept -> const_iterator {
return {}; }
565 constexpr auto end()
const noexcept -> const_iterator {
return {}; }
571 constexpr auto rbegin()
noexcept -> reverse_iterator {
return {}; }
577 constexpr auto rend()
noexcept -> reverse_iterator {
return {}; }
583 constexpr auto rbegin()
const noexcept -> const_reverse_iterator {
return {}; }
589 constexpr auto rend()
const noexcept -> const_reverse_iterator {
return {}; }
594 static constexpr auto cbegin()
noexcept -> const_iterator {
return {}; }
598 static constexpr auto cend()
noexcept -> const_iterator {
return {}; }
602 static constexpr auto crbegin()
noexcept -> const_reverse_iterator {
return {}; }
606 static constexpr auto crend()
noexcept -> const_reverse_iterator {
return {}; }
618 ARENE_NORETURN
constexpr auto operator[](std::size_t)
noexcept -> T& {
619 ARENE_PRECONDITION(!empty());
620 ARENE_INVARIANT_UNREACHABLE(
"Precondition always fires");
622 ARENE_NORETURN
constexpr auto operator[](std::size_t)
const noexcept -> T
const& {
623 ARENE_PRECONDITION(!empty());
624 ARENE_INVARIANT_UNREACHABLE(
"Precondition always fires");
644 bool AreExceptionsEnabled = detail::are_exceptions_enabled::value,
645 constraints<std::enable_if_t<AreExceptionsEnabled>> =
nullptr>
646 ARENE_NORETURN
constexpr auto at(std::size_t) -> T& {
647 array_detail::throw_out_of_range();
661 bool AreExceptionsEnabled = detail::are_exceptions_enabled::value,
662 constraints<std::enable_if_t<AreExceptionsEnabled>> =
nullptr>
663 ARENE_NORETURN
constexpr auto at(std::size_t)
const -> T
const& {
664 array_detail::throw_out_of_range();
678 ARENE_NORETURN
constexpr auto front()
noexcept -> T& {
679 ARENE_PRECONDITION(!empty());
680 ARENE_INVARIANT_UNREACHABLE(
"Precondition always fires");
694 ARENE_NORETURN
constexpr auto front()
const noexcept -> T
const& {
695 ARENE_PRECONDITION(!empty());
696 ARENE_INVARIANT_UNREACHABLE(
"Precondition always fires");
710 ARENE_NORETURN
constexpr auto back()
noexcept -> T& {
711 ARENE_PRECONDITION(!empty());
712 ARENE_INVARIANT_UNREACHABLE(
"Precondition always fires");
726 ARENE_NORETURN
constexpr auto back()
const noexcept -> T
const& {
727 ARENE_PRECONDITION(!empty());
728 ARENE_INVARIANT_UNREACHABLE(
"Precondition always fires");
738 static constexpr void fill(T
const&)
noexcept {}
744 constexpr void swap(array&)
noexcept {}
751 friend constexpr void swap(array&, array&)
noexcept {}
763 template <std::size_t UN>
764 static constexpr auto three_way_compare(array
const&, array<T, UN>
const&)
noexcept -> arene::base::strong_ordering {
765 return compare_three_way{}(0U, UN);
770 template <std::size_t UN>
771 friend constexpr auto operator==(array
const& lhs, array<T, UN>
const& rhs)
noexcept ->
bool {
772 return array::three_way_compare(lhs, rhs) == arene::base::strong_ordering::equal;
774 template <std::size_t UN>
775 friend constexpr auto operator!=(array
const& lhs, array<T, UN>
const& rhs)
noexcept ->
bool {
776 return !(lhs == rhs);
778 template <std::size_t UN>
779 friend constexpr auto operator<(array
const& lhs, array<T, UN>
const& rhs)
noexcept ->
bool {
780 return array::three_way_compare(lhs, rhs) == arene::base::strong_ordering::less;
782 template <std::size_t UN>
783 friend constexpr auto operator<=(array
const& lhs, array<T, UN>
const& rhs)
noexcept ->
bool {
784 return array::three_way_compare(lhs, rhs) != arene::base::strong_ordering::greater;
786 template <std::size_t UN>
787 friend constexpr auto operator>(array
const& lhs, array<T, UN>
const& rhs)
noexcept ->
bool {
788 return array::three_way_compare(lhs, rhs) == arene::base::strong_ordering::greater;
790 template <std::size_t UN>
791 friend constexpr auto operator>=(array
const& lhs, array<T, UN>
const& rhs)
noexcept ->
bool {
792 return array::three_way_compare(lhs, rhs) != arene::base::strong_ordering::less;