mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
libcxx: update to LLVM 21
This commit is contained in:
parent
e84e9d3a01
commit
d9f0fbf983
562 changed files with 16867 additions and 12974 deletions
134
lib/libcxx/include/__algorithm/copy.h
vendored
134
lib/libcxx/include/__algorithm/copy.h
vendored
|
|
@ -13,8 +13,10 @@
|
|||
#include <__algorithm/for_each_segment.h>
|
||||
#include <__algorithm/min.h>
|
||||
#include <__config>
|
||||
#include <__fwd/bit_reference.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__iterator/segmented_iterator.h>
|
||||
#include <__memory/pointer_traits.h>
|
||||
#include <__type_traits/common_type.h>
|
||||
#include <__type_traits/enable_if.h>
|
||||
#include <__utility/move.h>
|
||||
|
|
@ -29,9 +31,129 @@ _LIBCPP_PUSH_MACROS
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class _InputIterator, class _OutputIterator>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
|
||||
copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result);
|
||||
|
||||
template <class _InIter, class _Sent, class _OutIter>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter> __copy(_InIter, _Sent, _OutIter);
|
||||
|
||||
template <class _Cp, bool _IsConst>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_aligned(
|
||||
__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
|
||||
using _In = __bit_iterator<_Cp, _IsConst>;
|
||||
using difference_type = typename _In::difference_type;
|
||||
using __storage_type = typename _In::__storage_type;
|
||||
|
||||
const int __bits_per_word = _In::__bits_per_word;
|
||||
difference_type __n = __last - __first;
|
||||
if (__n > 0) {
|
||||
// do first word
|
||||
if (__first.__ctz_ != 0) {
|
||||
unsigned __clz = __bits_per_word - __first.__ctz_;
|
||||
difference_type __dn = std::min(static_cast<difference_type>(__clz), __n);
|
||||
__n -= __dn;
|
||||
__storage_type __m = std::__middle_mask<__storage_type>(__clz - __dn, __first.__ctz_);
|
||||
__storage_type __b = *__first.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b;
|
||||
__result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
|
||||
__result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
|
||||
++__first.__seg_;
|
||||
// __first.__ctz_ = 0;
|
||||
}
|
||||
// __first.__ctz_ == 0;
|
||||
// do middle words
|
||||
__storage_type __nw = __n / __bits_per_word;
|
||||
std::copy(std::__to_address(__first.__seg_),
|
||||
std::__to_address(__first.__seg_ + __nw),
|
||||
std::__to_address(__result.__seg_));
|
||||
__n -= __nw * __bits_per_word;
|
||||
__result.__seg_ += __nw;
|
||||
// do last word
|
||||
if (__n > 0) {
|
||||
__first.__seg_ += __nw;
|
||||
__storage_type __m = std::__trailing_mask<__storage_type>(__bits_per_word - __n);
|
||||
__storage_type __b = *__first.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b;
|
||||
__result.__ctz_ = static_cast<unsigned>(__n);
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _Cp, bool _IsConst>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_unaligned(
|
||||
__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
|
||||
using _In = __bit_iterator<_Cp, _IsConst>;
|
||||
using difference_type = typename _In::difference_type;
|
||||
using __storage_type = typename _In::__storage_type;
|
||||
|
||||
const int __bits_per_word = _In::__bits_per_word;
|
||||
difference_type __n = __last - __first;
|
||||
if (__n > 0) {
|
||||
// do first word
|
||||
if (__first.__ctz_ != 0) {
|
||||
unsigned __clz_f = __bits_per_word - __first.__ctz_;
|
||||
difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n);
|
||||
__n -= __dn;
|
||||
__storage_type __m = std::__middle_mask<__storage_type>(__clz_f - __dn, __first.__ctz_);
|
||||
__storage_type __b = *__first.__seg_ & __m;
|
||||
unsigned __clz_r = __bits_per_word - __result.__ctz_;
|
||||
__storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
|
||||
__m = std::__middle_mask<__storage_type>(__clz_r - __ddn, __result.__ctz_);
|
||||
*__result.__seg_ &= ~__m;
|
||||
if (__result.__ctz_ > __first.__ctz_)
|
||||
*__result.__seg_ |= __b << (__result.__ctz_ - __first.__ctz_);
|
||||
else
|
||||
*__result.__seg_ |= __b >> (__first.__ctz_ - __result.__ctz_);
|
||||
__result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word;
|
||||
__result.__ctz_ = static_cast<unsigned>((__ddn + __result.__ctz_) % __bits_per_word);
|
||||
__dn -= __ddn;
|
||||
if (__dn > 0) {
|
||||
__m = std::__trailing_mask<__storage_type>(__bits_per_word - __dn);
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b >> (__first.__ctz_ + __ddn);
|
||||
__result.__ctz_ = static_cast<unsigned>(__dn);
|
||||
}
|
||||
++__first.__seg_;
|
||||
// __first.__ctz_ = 0;
|
||||
}
|
||||
// __first.__ctz_ == 0;
|
||||
// do middle words
|
||||
unsigned __clz_r = __bits_per_word - __result.__ctz_;
|
||||
__storage_type __m = std::__leading_mask<__storage_type>(__result.__ctz_);
|
||||
for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) {
|
||||
__storage_type __b = *__first.__seg_;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b << __result.__ctz_;
|
||||
++__result.__seg_;
|
||||
*__result.__seg_ &= __m;
|
||||
*__result.__seg_ |= __b >> __clz_r;
|
||||
}
|
||||
// do last word
|
||||
if (__n > 0) {
|
||||
__m = std::__trailing_mask<__storage_type>(__bits_per_word - __n);
|
||||
__storage_type __b = *__first.__seg_ & __m;
|
||||
__storage_type __dn = std::min(__n, static_cast<difference_type>(__clz_r));
|
||||
__m = std::__middle_mask<__storage_type>(__clz_r - __dn, __result.__ctz_);
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b << __result.__ctz_;
|
||||
__result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
|
||||
__result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
|
||||
__n -= __dn;
|
||||
if (__n > 0) {
|
||||
__m = std::__trailing_mask<__storage_type>(__bits_per_word - __n);
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b >> __dn;
|
||||
__result.__ctz_ = static_cast<unsigned>(__n);
|
||||
}
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
struct __copy_impl {
|
||||
template <class _InIter, class _Sent, class _OutIter>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_InIter, _OutIter>
|
||||
|
|
@ -95,6 +217,16 @@ struct __copy_impl {
|
|||
}
|
||||
}
|
||||
|
||||
template <class _Cp, bool _IsConst>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, _IsConst>, __bit_iterator<_Cp, false> >
|
||||
operator()(__bit_iterator<_Cp, _IsConst> __first,
|
||||
__bit_iterator<_Cp, _IsConst> __last,
|
||||
__bit_iterator<_Cp, false> __result) const {
|
||||
if (__first.__ctz_ == __result.__ctz_)
|
||||
return std::make_pair(__last, std::__copy_aligned(__first, __last, __result));
|
||||
return std::make_pair(__last, std::__copy_unaligned(__first, __last, __result));
|
||||
}
|
||||
|
||||
// At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
|
||||
template <class _In, class _Out, __enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
|
||||
|
|
@ -110,7 +242,7 @@ __copy(_InIter __first, _Sent __last, _OutIter __result) {
|
|||
}
|
||||
|
||||
template <class _InputIterator, class _OutputIterator>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
|
||||
copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
|
||||
return std::__copy(__first, __last, __result).second;
|
||||
}
|
||||
|
|
|
|||
131
lib/libcxx/include/__algorithm/copy_backward.h
vendored
131
lib/libcxx/include/__algorithm/copy_backward.h
vendored
|
|
@ -10,11 +10,14 @@
|
|||
#define _LIBCPP___ALGORITHM_COPY_BACKWARD_H
|
||||
|
||||
#include <__algorithm/copy_move_common.h>
|
||||
#include <__algorithm/copy_n.h>
|
||||
#include <__algorithm/iterator_operations.h>
|
||||
#include <__algorithm/min.h>
|
||||
#include <__config>
|
||||
#include <__fwd/bit_reference.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__iterator/segmented_iterator.h>
|
||||
#include <__memory/pointer_traits.h>
|
||||
#include <__type_traits/common_type.h>
|
||||
#include <__type_traits/enable_if.h>
|
||||
#include <__type_traits/is_constructible.h>
|
||||
|
|
@ -34,6 +37,124 @@ template <class _AlgPolicy, class _InIter, class _Sent, class _OutIter>
|
|||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_InIter, _OutIter>
|
||||
__copy_backward(_InIter __first, _Sent __last, _OutIter __result);
|
||||
|
||||
template <class _Cp, bool _IsConst>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_backward_aligned(
|
||||
__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
|
||||
using _In = __bit_iterator<_Cp, _IsConst>;
|
||||
using difference_type = typename _In::difference_type;
|
||||
using __storage_type = typename _In::__storage_type;
|
||||
|
||||
const int __bits_per_word = _In::__bits_per_word;
|
||||
difference_type __n = __last - __first;
|
||||
if (__n > 0) {
|
||||
// do first word
|
||||
if (__last.__ctz_ != 0) {
|
||||
difference_type __dn = std::min(static_cast<difference_type>(__last.__ctz_), __n);
|
||||
__n -= __dn;
|
||||
unsigned __clz = __bits_per_word - __last.__ctz_;
|
||||
__storage_type __m = std::__middle_mask<__storage_type>(__clz, __last.__ctz_ - __dn);
|
||||
__storage_type __b = *__last.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b;
|
||||
__result.__ctz_ = static_cast<unsigned>(((-__dn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word);
|
||||
// __last.__ctz_ = 0
|
||||
}
|
||||
// __last.__ctz_ == 0 || __n == 0
|
||||
// __result.__ctz_ == 0 || __n == 0
|
||||
// do middle words
|
||||
__storage_type __nw = __n / __bits_per_word;
|
||||
__result.__seg_ -= __nw;
|
||||
__last.__seg_ -= __nw;
|
||||
std::copy_n(std::__to_address(__last.__seg_), __nw, std::__to_address(__result.__seg_));
|
||||
__n -= __nw * __bits_per_word;
|
||||
// do last word
|
||||
if (__n > 0) {
|
||||
__storage_type __m = std::__leading_mask<__storage_type>(__bits_per_word - __n);
|
||||
__storage_type __b = *--__last.__seg_ & __m;
|
||||
*--__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b;
|
||||
__result.__ctz_ = static_cast<unsigned>(-__n & (__bits_per_word - 1));
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _Cp, bool _IsConst>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_backward_unaligned(
|
||||
__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
|
||||
using _In = __bit_iterator<_Cp, _IsConst>;
|
||||
using difference_type = typename _In::difference_type;
|
||||
using __storage_type = typename _In::__storage_type;
|
||||
|
||||
const int __bits_per_word = _In::__bits_per_word;
|
||||
difference_type __n = __last - __first;
|
||||
if (__n > 0) {
|
||||
// do first word
|
||||
if (__last.__ctz_ != 0) {
|
||||
difference_type __dn = std::min(static_cast<difference_type>(__last.__ctz_), __n);
|
||||
__n -= __dn;
|
||||
unsigned __clz_l = __bits_per_word - __last.__ctz_;
|
||||
__storage_type __m = std::__middle_mask<__storage_type>(__clz_l, __last.__ctz_ - __dn);
|
||||
__storage_type __b = *__last.__seg_ & __m;
|
||||
unsigned __clz_r = __bits_per_word - __result.__ctz_;
|
||||
__storage_type __ddn = std::min(__dn, static_cast<difference_type>(__result.__ctz_));
|
||||
if (__ddn > 0) {
|
||||
__m = std::__middle_mask<__storage_type>(__clz_r, __result.__ctz_ - __ddn);
|
||||
*__result.__seg_ &= ~__m;
|
||||
if (__result.__ctz_ > __last.__ctz_)
|
||||
*__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_);
|
||||
else
|
||||
*__result.__seg_ |= __b >> (__last.__ctz_ - __result.__ctz_);
|
||||
__result.__ctz_ = static_cast<unsigned>(((-__ddn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word);
|
||||
__dn -= __ddn;
|
||||
}
|
||||
if (__dn > 0) {
|
||||
// __result.__ctz_ == 0
|
||||
--__result.__seg_;
|
||||
__result.__ctz_ = static_cast<unsigned>(-__dn & (__bits_per_word - 1));
|
||||
__m = std::__leading_mask<__storage_type>(__result.__ctz_);
|
||||
*__result.__seg_ &= ~__m;
|
||||
__last.__ctz_ -= __dn + __ddn;
|
||||
*__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_);
|
||||
}
|
||||
// __last.__ctz_ = 0
|
||||
}
|
||||
// __last.__ctz_ == 0 || __n == 0
|
||||
// __result.__ctz_ != 0 || __n == 0
|
||||
// do middle words
|
||||
unsigned __clz_r = __bits_per_word - __result.__ctz_;
|
||||
__storage_type __m = std::__trailing_mask<__storage_type>(__clz_r);
|
||||
for (; __n >= __bits_per_word; __n -= __bits_per_word) {
|
||||
__storage_type __b = *--__last.__seg_;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b >> __clz_r;
|
||||
*--__result.__seg_ &= __m;
|
||||
*__result.__seg_ |= __b << __result.__ctz_;
|
||||
}
|
||||
// do last word
|
||||
if (__n > 0) {
|
||||
__m = std::__leading_mask<__storage_type>(__bits_per_word - __n);
|
||||
__storage_type __b = *--__last.__seg_ & __m;
|
||||
__clz_r = __bits_per_word - __result.__ctz_;
|
||||
__storage_type __dn = std::min(__n, static_cast<difference_type>(__result.__ctz_));
|
||||
__m = std::__middle_mask<__storage_type>(__clz_r, __result.__ctz_ - __dn);
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b >> (__bits_per_word - __result.__ctz_);
|
||||
__result.__ctz_ = static_cast<unsigned>(((-__dn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word);
|
||||
__n -= __dn;
|
||||
if (__n > 0) {
|
||||
// __result.__ctz_ == 0
|
||||
--__result.__seg_;
|
||||
__result.__ctz_ = static_cast<unsigned>(-__n & (__bits_per_word - 1));
|
||||
__m = std::__leading_mask<__storage_type>(__result.__ctz_);
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b << (__result.__ctz_ - (__bits_per_word - __n - __dn));
|
||||
}
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _AlgPolicy>
|
||||
struct __copy_backward_impl {
|
||||
template <class _InIter, class _Sent, class _OutIter>
|
||||
|
|
@ -107,6 +228,16 @@ struct __copy_backward_impl {
|
|||
}
|
||||
}
|
||||
|
||||
template <class _Cp, bool _IsConst>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, _IsConst>, __bit_iterator<_Cp, false> >
|
||||
operator()(__bit_iterator<_Cp, _IsConst> __first,
|
||||
__bit_iterator<_Cp, _IsConst> __last,
|
||||
__bit_iterator<_Cp, false> __result) {
|
||||
if (__last.__ctz_ == __result.__ctz_)
|
||||
return std::make_pair(__last, std::__copy_backward_aligned(__first, __last, __result));
|
||||
return std::make_pair(__last, std::__copy_backward_unaligned(__first, __last, __result));
|
||||
}
|
||||
|
||||
// At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
|
||||
template <class _In, class _Out, __enable_if_t<__can_lower_copy_assignment_to_memmove<_In, _Out>::value, int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
|
||||
|
|
|
|||
10
lib/libcxx/include/__algorithm/count.h
vendored
10
lib/libcxx/include/__algorithm/count.h
vendored
|
|
@ -55,18 +55,18 @@ __count_bool(__bit_iterator<_Cp, _IsConst> __first, typename __size_difference_t
|
|||
if (__first.__ctz_ != 0) {
|
||||
__storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
|
||||
__storage_type __dn = std::min(__clz_f, __n);
|
||||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
|
||||
__r = std::__libcpp_popcount(std::__invert_if<!_ToCount>(*__first.__seg_) & __m);
|
||||
__storage_type __m = std::__middle_mask<__storage_type>(__clz_f - __dn, __first.__ctz_);
|
||||
__r = std::__popcount(__storage_type(std::__invert_if<!_ToCount>(*__first.__seg_) & __m));
|
||||
__n -= __dn;
|
||||
++__first.__seg_;
|
||||
}
|
||||
// do middle whole words
|
||||
for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word)
|
||||
__r += std::__libcpp_popcount(std::__invert_if<!_ToCount>(*__first.__seg_));
|
||||
__r += std::__popcount(std::__invert_if<!_ToCount>(*__first.__seg_));
|
||||
// do last partial word
|
||||
if (__n > 0) {
|
||||
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__r += std::__libcpp_popcount(std::__invert_if<!_ToCount>(*__first.__seg_) & __m);
|
||||
__storage_type __m = std::__trailing_mask<__storage_type>(__bits_per_word - __n);
|
||||
__r += std::__popcount(__storage_type(std::__invert_if<!_ToCount>(*__first.__seg_) & __m));
|
||||
}
|
||||
return __r;
|
||||
}
|
||||
|
|
|
|||
160
lib/libcxx/include/__algorithm/equal.h
vendored
160
lib/libcxx/include/__algorithm/equal.h
vendored
|
|
@ -11,16 +11,20 @@
|
|||
#define _LIBCPP___ALGORITHM_EQUAL_H
|
||||
|
||||
#include <__algorithm/comp.h>
|
||||
#include <__algorithm/min.h>
|
||||
#include <__algorithm/unwrap_iter.h>
|
||||
#include <__config>
|
||||
#include <__functional/identity.h>
|
||||
#include <__fwd/bit_reference.h>
|
||||
#include <__iterator/distance.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__memory/pointer_traits.h>
|
||||
#include <__string/constexpr_c_functions.h>
|
||||
#include <__type_traits/desugars_to.h>
|
||||
#include <__type_traits/enable_if.h>
|
||||
#include <__type_traits/invoke.h>
|
||||
#include <__type_traits/is_equality_comparable.h>
|
||||
#include <__type_traits/is_same.h>
|
||||
#include <__type_traits/is_volatile.h>
|
||||
#include <__utility/move.h>
|
||||
|
||||
|
|
@ -33,6 +37,140 @@ _LIBCPP_PUSH_MACROS
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class _Cp, bool _IsConst1, bool _IsConst2>
|
||||
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool
|
||||
__equal_unaligned(__bit_iterator<_Cp, _IsConst1> __first1,
|
||||
__bit_iterator<_Cp, _IsConst1> __last1,
|
||||
__bit_iterator<_Cp, _IsConst2> __first2) {
|
||||
using _It = __bit_iterator<_Cp, _IsConst1>;
|
||||
using difference_type = typename _It::difference_type;
|
||||
using __storage_type = typename _It::__storage_type;
|
||||
|
||||
const int __bits_per_word = _It::__bits_per_word;
|
||||
difference_type __n = __last1 - __first1;
|
||||
if (__n > 0) {
|
||||
// do first word
|
||||
if (__first1.__ctz_ != 0) {
|
||||
unsigned __clz_f = __bits_per_word - __first1.__ctz_;
|
||||
difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n);
|
||||
__n -= __dn;
|
||||
__storage_type __m = std::__middle_mask<__storage_type>(__clz_f - __dn, __first1.__ctz_);
|
||||
__storage_type __b = *__first1.__seg_ & __m;
|
||||
unsigned __clz_r = __bits_per_word - __first2.__ctz_;
|
||||
__storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
|
||||
__m = std::__middle_mask<__storage_type>(__clz_r - __ddn, __first2.__ctz_);
|
||||
if (__first2.__ctz_ > __first1.__ctz_) {
|
||||
if (static_cast<__storage_type>(*__first2.__seg_ & __m) !=
|
||||
static_cast<__storage_type>(__b << (__first2.__ctz_ - __first1.__ctz_)))
|
||||
return false;
|
||||
} else {
|
||||
if (static_cast<__storage_type>(*__first2.__seg_ & __m) !=
|
||||
static_cast<__storage_type>(__b >> (__first1.__ctz_ - __first2.__ctz_)))
|
||||
return false;
|
||||
}
|
||||
__first2.__seg_ += (__ddn + __first2.__ctz_) / __bits_per_word;
|
||||
__first2.__ctz_ = static_cast<unsigned>((__ddn + __first2.__ctz_) % __bits_per_word);
|
||||
__dn -= __ddn;
|
||||
if (__dn > 0) {
|
||||
__m = std::__trailing_mask<__storage_type>(__bits_per_word - __n);
|
||||
if (static_cast<__storage_type>(*__first2.__seg_ & __m) !=
|
||||
static_cast<__storage_type>(__b >> (__first1.__ctz_ + __ddn)))
|
||||
return false;
|
||||
__first2.__ctz_ = static_cast<unsigned>(__dn);
|
||||
}
|
||||
++__first1.__seg_;
|
||||
// __first1.__ctz_ = 0;
|
||||
}
|
||||
// __first1.__ctz_ == 0;
|
||||
// do middle words
|
||||
unsigned __clz_r = __bits_per_word - __first2.__ctz_;
|
||||
__storage_type __m = std::__leading_mask<__storage_type>(__first2.__ctz_);
|
||||
for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_) {
|
||||
__storage_type __b = *__first1.__seg_;
|
||||
if (static_cast<__storage_type>(*__first2.__seg_ & __m) != static_cast<__storage_type>(__b << __first2.__ctz_))
|
||||
return false;
|
||||
++__first2.__seg_;
|
||||
if (static_cast<__storage_type>(*__first2.__seg_ & static_cast<__storage_type>(~__m)) !=
|
||||
static_cast<__storage_type>(__b >> __clz_r))
|
||||
return false;
|
||||
}
|
||||
// do last word
|
||||
if (__n > 0) {
|
||||
__m = std::__trailing_mask<__storage_type>(__bits_per_word - __n);
|
||||
__storage_type __b = *__first1.__seg_ & __m;
|
||||
__storage_type __dn = std::min(__n, static_cast<difference_type>(__clz_r));
|
||||
__m = std::__middle_mask<__storage_type>(__clz_r - __dn, __first2.__ctz_);
|
||||
if (static_cast<__storage_type>(*__first2.__seg_ & __m) != static_cast<__storage_type>(__b << __first2.__ctz_))
|
||||
return false;
|
||||
__first2.__seg_ += (__dn + __first2.__ctz_) / __bits_per_word;
|
||||
__first2.__ctz_ = static_cast<unsigned>((__dn + __first2.__ctz_) % __bits_per_word);
|
||||
__n -= __dn;
|
||||
if (__n > 0) {
|
||||
__m = std::__trailing_mask<__storage_type>(__bits_per_word - __n);
|
||||
if (static_cast<__storage_type>(*__first2.__seg_ & __m) != static_cast<__storage_type>(__b >> __dn))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class _Cp, bool _IsConst1, bool _IsConst2>
|
||||
[[__nodiscard__]] _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool
|
||||
__equal_aligned(__bit_iterator<_Cp, _IsConst1> __first1,
|
||||
__bit_iterator<_Cp, _IsConst1> __last1,
|
||||
__bit_iterator<_Cp, _IsConst2> __first2) {
|
||||
using _It = __bit_iterator<_Cp, _IsConst1>;
|
||||
using difference_type = typename _It::difference_type;
|
||||
using __storage_type = typename _It::__storage_type;
|
||||
|
||||
const int __bits_per_word = _It::__bits_per_word;
|
||||
difference_type __n = __last1 - __first1;
|
||||
if (__n > 0) {
|
||||
// do first word
|
||||
if (__first1.__ctz_ != 0) {
|
||||
unsigned __clz = __bits_per_word - __first1.__ctz_;
|
||||
difference_type __dn = std::min(static_cast<difference_type>(__clz), __n);
|
||||
__n -= __dn;
|
||||
__storage_type __m = std::__middle_mask<__storage_type>(__clz - __dn, __first1.__ctz_);
|
||||
if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m))
|
||||
return false;
|
||||
++__first2.__seg_;
|
||||
++__first1.__seg_;
|
||||
// __first1.__ctz_ = 0;
|
||||
// __first2.__ctz_ = 0;
|
||||
}
|
||||
// __first1.__ctz_ == 0;
|
||||
// __first2.__ctz_ == 0;
|
||||
// do middle words
|
||||
for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_, ++__first2.__seg_)
|
||||
if (*__first2.__seg_ != *__first1.__seg_)
|
||||
return false;
|
||||
// do last word
|
||||
if (__n > 0) {
|
||||
__storage_type __m = std::__trailing_mask<__storage_type>(__bits_per_word - __n);
|
||||
if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class _Cp,
|
||||
bool _IsConst1,
|
||||
bool _IsConst2,
|
||||
class _BinaryPredicate,
|
||||
__enable_if_t<__desugars_to_v<__equal_tag, _BinaryPredicate, bool, bool>, int> = 0>
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl(
|
||||
__bit_iterator<_Cp, _IsConst1> __first1,
|
||||
__bit_iterator<_Cp, _IsConst1> __last1,
|
||||
__bit_iterator<_Cp, _IsConst2> __first2,
|
||||
_BinaryPredicate) {
|
||||
if (__first1.__ctz_ == __first2.__ctz_)
|
||||
return std::__equal_aligned(__first1, __last1, __first2);
|
||||
return std::__equal_unaligned(__first1, __last1, __first2);
|
||||
}
|
||||
|
||||
template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate>
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_iter_impl(
|
||||
_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate& __pred) {
|
||||
|
|
@ -94,6 +232,28 @@ __equal_impl(_Tp* __first1, _Tp* __last1, _Up* __first2, _Up*, _Pred&, _Proj1&,
|
|||
return std::__constexpr_memcmp_equal(__first1, __first2, __element_count(__last1 - __first1));
|
||||
}
|
||||
|
||||
template <class _Cp,
|
||||
bool _IsConst1,
|
||||
bool _IsConst2,
|
||||
class _Pred,
|
||||
class _Proj1,
|
||||
class _Proj2,
|
||||
__enable_if_t<__desugars_to_v<__equal_tag, _Pred, bool, bool> && __is_identity<_Proj1>::value &&
|
||||
__is_identity<_Proj2>::value,
|
||||
int> = 0>
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool __equal_impl(
|
||||
__bit_iterator<_Cp, _IsConst1> __first1,
|
||||
__bit_iterator<_Cp, _IsConst1> __last1,
|
||||
__bit_iterator<_Cp, _IsConst2> __first2,
|
||||
__bit_iterator<_Cp, _IsConst2>,
|
||||
_Pred&,
|
||||
_Proj1&,
|
||||
_Proj2&) {
|
||||
if (__first1.__ctz_ == __first2.__ctz_)
|
||||
return std::__equal_aligned(__first1, __last1, __first2);
|
||||
return std::__equal_unaligned(__first1, __last1, __first2);
|
||||
}
|
||||
|
||||
template <class _InputIterator1, class _InputIterator2, class _BinaryPredicate>
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
|
||||
equal(_InputIterator1 __first1,
|
||||
|
|
|
|||
12
lib/libcxx/include/__algorithm/fill_n.h
vendored
12
lib/libcxx/include/__algorithm/fill_n.h
vendored
|
|
@ -41,11 +41,7 @@ __fill_n_bool(__bit_iterator<_Cp, false> __first, typename __size_difference_typ
|
|||
if (__first.__ctz_ != 0) {
|
||||
__storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
|
||||
__storage_type __dn = std::min(__clz_f, __n);
|
||||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
|
||||
if (_FillVal)
|
||||
*__first.__seg_ |= __m;
|
||||
else
|
||||
*__first.__seg_ &= ~__m;
|
||||
std::__fill_masked_range(std::__to_address(__first.__seg_), __clz_f - __dn, __first.__ctz_, _FillVal);
|
||||
__n -= __dn;
|
||||
++__first.__seg_;
|
||||
}
|
||||
|
|
@ -56,11 +52,7 @@ __fill_n_bool(__bit_iterator<_Cp, false> __first, typename __size_difference_typ
|
|||
// do last partial word
|
||||
if (__n > 0) {
|
||||
__first.__seg_ += __nw;
|
||||
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
if (_FillVal)
|
||||
*__first.__seg_ |= __m;
|
||||
else
|
||||
*__first.__seg_ &= ~__m;
|
||||
std::__fill_masked_range(std::__to_address(__first.__seg_), __bits_per_word - __n, 0u, _FillVal);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
10
lib/libcxx/include/__algorithm/find.h
vendored
10
lib/libcxx/include/__algorithm/find.h
vendored
|
|
@ -106,10 +106,10 @@ __find_bool(__bit_iterator<_Cp, _IsConst> __first, typename __size_difference_ty
|
|||
if (__first.__ctz_ != 0) {
|
||||
__storage_type __clz_f = static_cast<__storage_type>(__bits_per_word - __first.__ctz_);
|
||||
__storage_type __dn = std::min(__clz_f, __n);
|
||||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
|
||||
__storage_type __m = std::__middle_mask<__storage_type>(__clz_f - __dn, __first.__ctz_);
|
||||
__storage_type __b = std::__invert_if<!_ToFind>(*__first.__seg_) & __m;
|
||||
if (__b)
|
||||
return _It(__first.__seg_, static_cast<unsigned>(std::__libcpp_ctz(__b)));
|
||||
return _It(__first.__seg_, static_cast<unsigned>(std::__countr_zero(__b)));
|
||||
if (__n == __dn)
|
||||
return __first + __n;
|
||||
__n -= __dn;
|
||||
|
|
@ -119,14 +119,14 @@ __find_bool(__bit_iterator<_Cp, _IsConst> __first, typename __size_difference_ty
|
|||
for (; __n >= __bits_per_word; ++__first.__seg_, __n -= __bits_per_word) {
|
||||
__storage_type __b = std::__invert_if<!_ToFind>(*__first.__seg_);
|
||||
if (__b)
|
||||
return _It(__first.__seg_, static_cast<unsigned>(std::__libcpp_ctz(__b)));
|
||||
return _It(__first.__seg_, static_cast<unsigned>(std::__countr_zero(__b)));
|
||||
}
|
||||
// do last partial word
|
||||
if (__n > 0) {
|
||||
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__storage_type __m = std::__trailing_mask<__storage_type>(__bits_per_word - __n);
|
||||
__storage_type __b = std::__invert_if<!_ToFind>(*__first.__seg_) & __m;
|
||||
if (__b)
|
||||
return _It(__first.__seg_, static_cast<unsigned>(std::__libcpp_ctz(__b)));
|
||||
return _It(__first.__seg_, static_cast<unsigned>(std::__countr_zero(__b)));
|
||||
}
|
||||
return _It(__first.__seg_, static_cast<unsigned>(__n));
|
||||
}
|
||||
|
|
|
|||
47
lib/libcxx/include/__algorithm/for_each.h
vendored
47
lib/libcxx/include/__algorithm/for_each.h
vendored
|
|
@ -12,9 +12,10 @@
|
|||
|
||||
#include <__algorithm/for_each_segment.h>
|
||||
#include <__config>
|
||||
#include <__functional/identity.h>
|
||||
#include <__iterator/segmented_iterator.h>
|
||||
#include <__ranges/movable_box.h>
|
||||
#include <__utility/in_place.h>
|
||||
#include <__type_traits/enable_if.h>
|
||||
#include <__type_traits/invoke.h>
|
||||
#include <__utility/move.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
|
|
@ -26,28 +27,36 @@ _LIBCPP_PUSH_MACROS
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class _InputIterator, class _Function>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Function
|
||||
for_each(_InputIterator __first, _InputIterator __last, _Function __f) {
|
||||
template <class _InputIterator, class _Sent, class _Func, class _Proj>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
|
||||
__for_each(_InputIterator __first, _Sent __last, _Func& __f, _Proj& __proj) {
|
||||
for (; __first != __last; ++__first)
|
||||
__f(*__first);
|
||||
return __f;
|
||||
std::__invoke(__f, std::__invoke(__proj, *__first));
|
||||
return __first;
|
||||
}
|
||||
|
||||
// __movable_box is available in C++20, but is actually a copyable-box, so optimization is only correct in C++23
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
template <class _SegmentedIterator, class _Function>
|
||||
requires __is_segmented_iterator<_SegmentedIterator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Function
|
||||
for_each(_SegmentedIterator __first, _SegmentedIterator __last, _Function __func) {
|
||||
ranges::__movable_box<_Function> __wrapped_func(in_place, std::move(__func));
|
||||
std::__for_each_segment(__first, __last, [&](auto __lfirst, auto __llast) {
|
||||
__wrapped_func =
|
||||
ranges::__movable_box<_Function>(in_place, std::for_each(__lfirst, __llast, std::move(*__wrapped_func)));
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class _SegmentedIterator,
|
||||
class _Func,
|
||||
class _Proj,
|
||||
__enable_if_t<__is_segmented_iterator<_SegmentedIterator>::value, int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _SegmentedIterator
|
||||
__for_each(_SegmentedIterator __first, _SegmentedIterator __last, _Func& __func, _Proj& __proj) {
|
||||
using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator;
|
||||
std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
|
||||
std::__for_each(__lfirst, __llast, __func, __proj);
|
||||
});
|
||||
return std::move(*__wrapped_func);
|
||||
return __last;
|
||||
}
|
||||
#endif // !_LIBCPP_CXX03_LANG
|
||||
|
||||
template <class _InputIterator, class _Func>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Func
|
||||
for_each(_InputIterator __first, _InputIterator __last, _Func __f) {
|
||||
__identity __proj;
|
||||
std::__for_each(__first, __last, __f, __proj);
|
||||
return __f;
|
||||
}
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
|
|
|
|||
77
lib/libcxx/include/__algorithm/for_each_n.h
vendored
77
lib/libcxx/include/__algorithm/for_each_n.h
vendored
|
|
@ -10,32 +10,93 @@
|
|||
#ifndef _LIBCPP___ALGORITHM_FOR_EACH_N_H
|
||||
#define _LIBCPP___ALGORITHM_FOR_EACH_N_H
|
||||
|
||||
#include <__algorithm/for_each.h>
|
||||
#include <__algorithm/for_each_n_segment.h>
|
||||
#include <__config>
|
||||
#include <__functional/identity.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__iterator/segmented_iterator.h>
|
||||
#include <__type_traits/disjunction.h>
|
||||
#include <__type_traits/enable_if.h>
|
||||
#include <__type_traits/invoke.h>
|
||||
#include <__type_traits/negation.h>
|
||||
#include <__utility/convert_to_integral.h>
|
||||
#include <__utility/move.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
|
||||
template <class _InputIterator, class _Size, class _Function>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
|
||||
for_each_n(_InputIterator __first, _Size __orig_n, _Function __f) {
|
||||
template <class _InputIterator,
|
||||
class _Size,
|
||||
class _Func,
|
||||
class _Proj,
|
||||
__enable_if_t<!__has_random_access_iterator_category<_InputIterator>::value &&
|
||||
_Or< _Not<__is_segmented_iterator<_InputIterator> >,
|
||||
_Not<__has_random_access_local_iterator<_InputIterator> > >::value,
|
||||
int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
|
||||
__for_each_n(_InputIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj) {
|
||||
typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize;
|
||||
_IntegralSize __n = __orig_n;
|
||||
while (__n > 0) {
|
||||
__f(*__first);
|
||||
std::__invoke(__f, std::__invoke(__proj, *__first));
|
||||
++__first;
|
||||
--__n;
|
||||
}
|
||||
return __first;
|
||||
return std::move(__first);
|
||||
}
|
||||
|
||||
#endif
|
||||
template <class _RandIter,
|
||||
class _Size,
|
||||
class _Func,
|
||||
class _Proj,
|
||||
__enable_if_t<__has_random_access_iterator_category<_RandIter>::value, int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandIter
|
||||
__for_each_n(_RandIter __first, _Size __orig_n, _Func& __f, _Proj& __proj) {
|
||||
typename std::iterator_traits<_RandIter>::difference_type __n = __orig_n;
|
||||
auto __last = __first + __n;
|
||||
std::__for_each(__first, __last, __f, __proj);
|
||||
return __last;
|
||||
}
|
||||
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
template <class _SegmentedIterator,
|
||||
class _Size,
|
||||
class _Func,
|
||||
class _Proj,
|
||||
__enable_if_t<!__has_random_access_iterator_category<_SegmentedIterator>::value &&
|
||||
__is_segmented_iterator<_SegmentedIterator>::value &&
|
||||
__has_random_access_iterator_category<
|
||||
typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator>::value,
|
||||
int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _SegmentedIterator
|
||||
__for_each_n(_SegmentedIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj) {
|
||||
using __local_iterator_t = typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator;
|
||||
return std::__for_each_n_segment(__first, __orig_n, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
|
||||
std::__for_each(__lfirst, __llast, __f, __proj);
|
||||
});
|
||||
}
|
||||
#endif // !_LIBCPP_CXX03_LANG
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
|
||||
template <class _InputIterator, class _Size, class _Func>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
|
||||
for_each_n(_InputIterator __first, _Size __orig_n, _Func __f) {
|
||||
__identity __proj;
|
||||
return std::__for_each_n(__first, __orig_n, __f, __proj);
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 17
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___ALGORITHM_FOR_EACH_N_H
|
||||
|
|
|
|||
63
lib/libcxx/include/__algorithm/for_each_n_segment.h
vendored
Normal file
63
lib/libcxx/include/__algorithm/for_each_n_segment.h
vendored
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___ALGORITHM_FOR_EACH_N_SEGMENT_H
|
||||
#define _LIBCPP___ALGORITHM_FOR_EACH_N_SEGMENT_H
|
||||
|
||||
#include <__config>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__iterator/segmented_iterator.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
// __for_each_n_segment optimizes linear iteration over segmented iterators. It processes a segmented
|
||||
// input range [__first, __first + __n) by applying the functor __func to each element within the segment.
|
||||
// The return value of __func is ignored, and the function returns an iterator pointing to one past the
|
||||
// last processed element in the input range.
|
||||
|
||||
template <class _SegmentedIterator, class _Size, class _Functor>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _SegmentedIterator
|
||||
__for_each_n_segment(_SegmentedIterator __first, _Size __orig_n, _Functor __func) {
|
||||
static_assert(__is_segmented_iterator<_SegmentedIterator>::value &&
|
||||
__has_random_access_iterator_category<
|
||||
typename __segmented_iterator_traits<_SegmentedIterator>::__local_iterator>::value,
|
||||
"__for_each_n_segment only works with segmented iterators with random-access local iterators");
|
||||
if (__orig_n <= 0)
|
||||
return __first;
|
||||
|
||||
using _Traits = __segmented_iterator_traits<_SegmentedIterator>;
|
||||
using __local_iter_t = typename _Traits::__local_iterator;
|
||||
using __difference_t = typename std::iterator_traits<__local_iter_t>::difference_type;
|
||||
__difference_t __n = __orig_n;
|
||||
auto __seg = _Traits::__segment(__first);
|
||||
auto __local_first = _Traits::__local(__first);
|
||||
__local_iter_t __local_last;
|
||||
|
||||
while (__n > 0) {
|
||||
__local_last = _Traits::__end(__seg);
|
||||
auto __seg_size = __local_last - __local_first;
|
||||
if (__n <= __seg_size) {
|
||||
__local_last = __local_first + __n;
|
||||
__func(__local_first, __local_last);
|
||||
break;
|
||||
}
|
||||
__func(__local_first, __local_last);
|
||||
__n -= __seg_size;
|
||||
__local_first = _Traits::__begin(++__seg);
|
||||
}
|
||||
|
||||
return _Traits::__compose(__seg, __local_last);
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___ALGORITHM_FOR_EACH_N_SEGMENT_H
|
||||
11
lib/libcxx/include/__algorithm/inplace_merge.h
vendored
11
lib/libcxx/include/__algorithm/inplace_merge.h
vendored
|
|
@ -22,6 +22,7 @@
|
|||
#include <__functional/identity.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__iterator/reverse_iterator.h>
|
||||
#include <__memory/construct_at.h>
|
||||
#include <__memory/destruct_n.h>
|
||||
#include <__memory/unique_ptr.h>
|
||||
#include <__memory/unique_temporary_buffer.h>
|
||||
|
|
@ -106,13 +107,13 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __buffered_inplace_merg
|
|||
value_type* __p = __buff;
|
||||
for (_BidirectionalIterator __i = __first; __i != __middle;
|
||||
__d.template __incr<value_type>(), (void)++__i, (void)++__p)
|
||||
::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i));
|
||||
std::__construct_at(__p, _IterOps<_AlgPolicy>::__iter_move(__i));
|
||||
std::__half_inplace_merge<_AlgPolicy>(__buff, __p, __middle, __last, __first, __comp);
|
||||
} else {
|
||||
value_type* __p = __buff;
|
||||
for (_BidirectionalIterator __i = __middle; __i != __last;
|
||||
__d.template __incr<value_type>(), (void)++__i, (void)++__p)
|
||||
::new ((void*)__p) value_type(_IterOps<_AlgPolicy>::__iter_move(__i));
|
||||
std::__construct_at(__p, _IterOps<_AlgPolicy>::__iter_move(__i));
|
||||
typedef reverse_iterator<_BidirectionalIterator> _RBi;
|
||||
typedef reverse_iterator<value_type*> _Rv;
|
||||
typedef __invert<_Compare> _Inverted;
|
||||
|
|
@ -203,7 +204,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void __inplace_merge(
|
|||
}
|
||||
|
||||
template <class _AlgPolicy, class _BidirectionalIterator, class _Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI void __inplace_merge(
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __inplace_merge(
|
||||
_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare&& __comp) {
|
||||
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
|
||||
typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type;
|
||||
|
|
@ -223,14 +224,14 @@ _LIBCPP_HIDE_FROM_ABI void __inplace_merge(
|
|||
}
|
||||
|
||||
template <class _BidirectionalIterator, class _Compare>
|
||||
inline _LIBCPP_HIDE_FROM_ABI void inplace_merge(
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void inplace_merge(
|
||||
_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last, _Compare __comp) {
|
||||
std::__inplace_merge<_ClassicAlgPolicy>(
|
||||
std::move(__first), std::move(__middle), std::move(__last), static_cast<__comp_ref_type<_Compare> >(__comp));
|
||||
}
|
||||
|
||||
template <class _BidirectionalIterator>
|
||||
inline _LIBCPP_HIDE_FROM_ABI void
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
|
||||
inplace_merge(_BidirectionalIterator __first, _BidirectionalIterator __middle, _BidirectionalIterator __last) {
|
||||
std::inplace_merge(std::move(__first), std::move(__middle), std::move(__last), __less<>());
|
||||
}
|
||||
|
|
|
|||
2
lib/libcxx/include/__algorithm/min_element.h
vendored
2
lib/libcxx/include/__algorithm/min_element.h
vendored
|
|
@ -29,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
|
||||
template <class _Comp, class _Iter, class _Sent, class _Proj>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter
|
||||
__min_element(_Iter __first, _Sent __last, _Comp __comp, _Proj& __proj) {
|
||||
__min_element(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
|
||||
if (__first == __last)
|
||||
return __first;
|
||||
|
||||
|
|
|
|||
10
lib/libcxx/include/__algorithm/move.h
vendored
10
lib/libcxx/include/__algorithm/move.h
vendored
|
|
@ -9,11 +9,13 @@
|
|||
#ifndef _LIBCPP___ALGORITHM_MOVE_H
|
||||
#define _LIBCPP___ALGORITHM_MOVE_H
|
||||
|
||||
#include <__algorithm/copy.h>
|
||||
#include <__algorithm/copy_move_common.h>
|
||||
#include <__algorithm/for_each_segment.h>
|
||||
#include <__algorithm/iterator_operations.h>
|
||||
#include <__algorithm/min.h>
|
||||
#include <__config>
|
||||
#include <__fwd/bit_reference.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__iterator/segmented_iterator.h>
|
||||
#include <__type_traits/common_type.h>
|
||||
|
|
@ -98,6 +100,14 @@ struct __move_impl {
|
|||
}
|
||||
}
|
||||
|
||||
template <class _Cp, bool _IsConst>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, _IsConst>, __bit_iterator<_Cp, false> >
|
||||
operator()(__bit_iterator<_Cp, _IsConst> __first,
|
||||
__bit_iterator<_Cp, _IsConst> __last,
|
||||
__bit_iterator<_Cp, false> __result) {
|
||||
return std::__copy(__first, __last, __result);
|
||||
}
|
||||
|
||||
// At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
|
||||
template <class _In, class _Out, __enable_if_t<__can_lower_move_assignment_to_memmove<_In, _Out>::value, int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
|
||||
|
|
|
|||
10
lib/libcxx/include/__algorithm/move_backward.h
vendored
10
lib/libcxx/include/__algorithm/move_backward.h
vendored
|
|
@ -9,10 +9,12 @@
|
|||
#ifndef _LIBCPP___ALGORITHM_MOVE_BACKWARD_H
|
||||
#define _LIBCPP___ALGORITHM_MOVE_BACKWARD_H
|
||||
|
||||
#include <__algorithm/copy_backward.h>
|
||||
#include <__algorithm/copy_move_common.h>
|
||||
#include <__algorithm/iterator_operations.h>
|
||||
#include <__algorithm/min.h>
|
||||
#include <__config>
|
||||
#include <__fwd/bit_reference.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__iterator/segmented_iterator.h>
|
||||
#include <__type_traits/common_type.h>
|
||||
|
|
@ -107,6 +109,14 @@ struct __move_backward_impl {
|
|||
}
|
||||
}
|
||||
|
||||
template <class _Cp, bool _IsConst>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, _IsConst>, __bit_iterator<_Cp, false> >
|
||||
operator()(__bit_iterator<_Cp, _IsConst> __first,
|
||||
__bit_iterator<_Cp, _IsConst> __last,
|
||||
__bit_iterator<_Cp, false> __result) {
|
||||
return std::__copy_backward<_ClassicAlgPolicy>(__first, __last, __result);
|
||||
}
|
||||
|
||||
// At this point, the iterators have been unwrapped so any `contiguous_iterator` has been unwrapped to a pointer.
|
||||
template <class _In, class _Out, __enable_if_t<__can_lower_move_assignment_to_memmove<_In, _Out>::value, int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
|
||||
|
|
|
|||
56
lib/libcxx/include/__algorithm/out_value_result.h
vendored
Normal file
56
lib/libcxx/include/__algorithm/out_value_result.h
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___ALGORITHM_OUT_VALUE_RESULT_H
|
||||
#define _LIBCPP___ALGORITHM_OUT_VALUE_RESULT_H
|
||||
|
||||
#include <__concepts/convertible_to.h>
|
||||
#include <__config>
|
||||
#include <__utility/move.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
|
||||
namespace ranges {
|
||||
|
||||
template <class _OutIter1, class _ValType1>
|
||||
struct out_value_result {
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS _OutIter1 out;
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS _ValType1 value;
|
||||
|
||||
template <class _OutIter2, class _ValType2>
|
||||
requires convertible_to<const _OutIter1&, _OutIter2> && convertible_to<const _ValType1&, _ValType2>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr operator out_value_result<_OutIter2, _ValType2>() const& {
|
||||
return {out, value};
|
||||
}
|
||||
|
||||
template <class _OutIter2, class _ValType2>
|
||||
requires convertible_to<_OutIter1, _OutIter2> && convertible_to<_ValType1, _ValType2>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr operator out_value_result<_OutIter2, _ValType2>() && {
|
||||
return {std::move(out), std::move(value)};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ranges
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___ALGORITHM_OUT_VALUE_RESULT_H
|
||||
125
lib/libcxx/include/__algorithm/radix_sort.h
vendored
125
lib/libcxx/include/__algorithm/radix_sort.h
vendored
|
|
@ -29,10 +29,12 @@
|
|||
|
||||
#include <__algorithm/for_each.h>
|
||||
#include <__algorithm/move.h>
|
||||
#include <__bit/bit_cast.h>
|
||||
#include <__bit/bit_log2.h>
|
||||
#include <__bit/countl.h>
|
||||
#include <__config>
|
||||
#include <__cstddef/size_t.h>
|
||||
#include <__functional/identity.h>
|
||||
#include <__iterator/access.h>
|
||||
#include <__iterator/distance.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__iterator/move_iterator.h>
|
||||
|
|
@ -43,9 +45,12 @@
|
|||
#include <__type_traits/enable_if.h>
|
||||
#include <__type_traits/invoke.h>
|
||||
#include <__type_traits/is_assignable.h>
|
||||
#include <__type_traits/is_enum.h>
|
||||
#include <__type_traits/is_integral.h>
|
||||
#include <__type_traits/is_unsigned.h>
|
||||
#include <__type_traits/make_unsigned.h>
|
||||
#include <__type_traits/void_t.h>
|
||||
#include <__utility/declval.h>
|
||||
#include <__utility/forward.h>
|
||||
#include <__utility/integer_sequence.h>
|
||||
#include <__utility/move.h>
|
||||
|
|
@ -67,7 +72,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
#if _LIBCPP_STD_VER >= 14
|
||||
|
||||
template <class _InputIterator, class _OutputIterator>
|
||||
_LIBCPP_HIDE_FROM_ABI pair<_OutputIterator, __iter_value_type<_InputIterator>>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr pair<_OutputIterator, __iter_value_type<_InputIterator>>
|
||||
__partial_sum_max(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
|
||||
if (__first == __last)
|
||||
return {__result, 0};
|
||||
|
|
@ -109,7 +114,7 @@ struct __counting_sort_traits {
|
|||
};
|
||||
|
||||
template <class _Radix, class _Integer>
|
||||
_LIBCPP_HIDE_FROM_ABI auto __nth_radix(size_t __radix_number, _Radix __radix, _Integer __n) {
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto __nth_radix(size_t __radix_number, _Radix __radix, _Integer __n) {
|
||||
static_assert(is_unsigned<_Integer>::value);
|
||||
using __traits = __counting_sort_traits<_Integer, _Radix>;
|
||||
|
||||
|
|
@ -117,7 +122,7 @@ _LIBCPP_HIDE_FROM_ABI auto __nth_radix(size_t __radix_number, _Radix __radix, _I
|
|||
}
|
||||
|
||||
template <class _ForwardIterator, class _Map, class _RandomAccessIterator>
|
||||
_LIBCPP_HIDE_FROM_ABI void
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void
|
||||
__collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _RandomAccessIterator __counters) {
|
||||
using __value_type = __iter_value_type<_ForwardIterator>;
|
||||
using __traits = __counting_sort_traits<__value_type, _Map>;
|
||||
|
|
@ -129,7 +134,7 @@ __collect(_ForwardIterator __first, _ForwardIterator __last, _Map __map, _Random
|
|||
}
|
||||
|
||||
template <class _ForwardIterator, class _RandomAccessIterator1, class _Map, class _RandomAccessIterator2>
|
||||
_LIBCPP_HIDE_FROM_ABI void
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void
|
||||
__dispose(_ForwardIterator __first,
|
||||
_ForwardIterator __last,
|
||||
_RandomAccessIterator1 __result,
|
||||
|
|
@ -147,7 +152,7 @@ template <class _ForwardIterator,
|
|||
class _RandomAccessIterator1,
|
||||
class _RandomAccessIterator2,
|
||||
size_t... _Radices>
|
||||
_LIBCPP_HIDE_FROM_ABI bool __collect_impl(
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool __collect_impl(
|
||||
_ForwardIterator __first,
|
||||
_ForwardIterator __last,
|
||||
_Map __map,
|
||||
|
|
@ -177,7 +182,7 @@ _LIBCPP_HIDE_FROM_ABI bool __collect_impl(
|
|||
}
|
||||
|
||||
template <class _ForwardIterator, class _Map, class _Radix, class _RandomAccessIterator1, class _RandomAccessIterator2>
|
||||
_LIBCPP_HIDE_FROM_ABI bool
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr bool
|
||||
__collect(_ForwardIterator __first,
|
||||
_ForwardIterator __last,
|
||||
_Map __map,
|
||||
|
|
@ -191,7 +196,7 @@ __collect(_ForwardIterator __first,
|
|||
}
|
||||
|
||||
template <class _BidirectionalIterator, class _RandomAccessIterator1, class _Map, class _RandomAccessIterator2>
|
||||
_LIBCPP_HIDE_FROM_ABI void __dispose_backward(
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __dispose_backward(
|
||||
_BidirectionalIterator __first,
|
||||
_BidirectionalIterator __last,
|
||||
_RandomAccessIterator1 __result,
|
||||
|
|
@ -206,7 +211,7 @@ _LIBCPP_HIDE_FROM_ABI void __dispose_backward(
|
|||
}
|
||||
|
||||
template <class _ForwardIterator, class _RandomAccessIterator, class _Map>
|
||||
_LIBCPP_HIDE_FROM_ABI _RandomAccessIterator
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _RandomAccessIterator
|
||||
__counting_sort_impl(_ForwardIterator __first, _ForwardIterator __last, _RandomAccessIterator __result, _Map __map) {
|
||||
using __value_type = __iter_value_type<_ForwardIterator>;
|
||||
using __traits = __counting_sort_traits<__value_type, _Map>;
|
||||
|
|
@ -225,7 +230,7 @@ template <class _RandomAccessIterator1,
|
|||
class _Radix,
|
||||
enable_if_t< __radix_sort_traits<__iter_value_type<_RandomAccessIterator1>, _Map, _Radix>::__radix_count == 1,
|
||||
int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI void __radix_sort_impl(
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __radix_sort_impl(
|
||||
_RandomAccessIterator1 __first,
|
||||
_RandomAccessIterator1 __last,
|
||||
_RandomAccessIterator2 __buffer,
|
||||
|
|
@ -245,7 +250,7 @@ template <
|
|||
class _Radix,
|
||||
enable_if_t< __radix_sort_traits<__iter_value_type<_RandomAccessIterator1>, _Map, _Radix>::__radix_count % 2 == 0,
|
||||
int> = 0 >
|
||||
_LIBCPP_HIDE_FROM_ABI void __radix_sort_impl(
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void __radix_sort_impl(
|
||||
_RandomAccessIterator1 __first,
|
||||
_RandomAccessIterator1 __last,
|
||||
_RandomAccessIterator2 __buffer_begin,
|
||||
|
|
@ -297,6 +302,96 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __shift_to_unsigned(_Ip __n) {
|
|||
return static_cast<make_unsigned_t<_Ip> >(__n ^ __min_value);
|
||||
}
|
||||
|
||||
template <size_t _Size>
|
||||
struct __unsigned_integer_of_size;
|
||||
|
||||
template <>
|
||||
struct __unsigned_integer_of_size<1> {
|
||||
using type _LIBCPP_NODEBUG = uint8_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct __unsigned_integer_of_size<2> {
|
||||
using type _LIBCPP_NODEBUG = uint16_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct __unsigned_integer_of_size<4> {
|
||||
using type _LIBCPP_NODEBUG = uint32_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct __unsigned_integer_of_size<8> {
|
||||
using type _LIBCPP_NODEBUG = uint64_t;
|
||||
};
|
||||
|
||||
# if _LIBCPP_HAS_INT128
|
||||
template <>
|
||||
struct __unsigned_integer_of_size<16> {
|
||||
using type _LIBCPP_NODEBUG = unsigned __int128;
|
||||
};
|
||||
# endif
|
||||
|
||||
template <size_t _Size>
|
||||
using __unsigned_integer_of_size_t _LIBCPP_NODEBUG = typename __unsigned_integer_of_size<_Size>::type;
|
||||
|
||||
template <class _Sc>
|
||||
using __unsigned_representation_for_t _LIBCPP_NODEBUG = __unsigned_integer_of_size_t<sizeof(_Sc)>;
|
||||
|
||||
// The function `__to_ordered_integral` is defined for integers and IEEE 754 floating-point numbers.
|
||||
// Returns an integer representation such that for any `x` and `y` such that `x < y`, the expression
|
||||
// `__to_ordered_integral(x) < __to_ordered_integral(y)` is true, where `x`, `y` are integers or IEEE 754 floats.
|
||||
template <class _Integral, enable_if_t< is_integral<_Integral>::value, int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral(_Integral __n) {
|
||||
return __n;
|
||||
}
|
||||
|
||||
// An overload for IEEE 754 floating-point numbers
|
||||
|
||||
// For the floats conforming to IEEE 754 (IEC 559) standard, we know that:
|
||||
// 1. The bit representation of positive floats directly reflects their order:
|
||||
// When comparing floats by magnitude, the number with the larger exponent is greater, and if the exponents are
|
||||
// equal, the one with the larger mantissa is greater.
|
||||
// 2. The bit representation of negative floats reflects their reverse order (for the same reasons).
|
||||
// 3. The most significant bit (sign bit) is zero for positive floats and one for negative floats. Therefore, in the raw
|
||||
// bit representation, any negative number will be greater than any positive number.
|
||||
|
||||
// The only exception from this rule is `NaN`, which is unordered by definition.
|
||||
|
||||
// Based on the above, to obtain correctly ordered integral representation of floating-point numbers, we need to:
|
||||
// 1. Invert the bit representation (including the sign bit) of negative floats to switch from reverse order to direct
|
||||
// order;
|
||||
// 2. Invert the sign bit for positive floats.
|
||||
|
||||
// Thus, in final integral representation, we have reversed the order for negative floats and made all negative floats
|
||||
// smaller than all positive numbers (by inverting the sign bit).
|
||||
template <class _Floating, enable_if_t< numeric_limits<_Floating>::is_iec559, int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral(_Floating __f) {
|
||||
using __integral_type = __unsigned_representation_for_t<_Floating>;
|
||||
constexpr auto __bit_count = std::numeric_limits<__integral_type>::digits;
|
||||
constexpr auto __sign_bit_mask = static_cast<__integral_type>(__integral_type{1} << (__bit_count - 1));
|
||||
|
||||
const auto __u = std::__bit_cast<__integral_type>(__f);
|
||||
|
||||
return static_cast<__integral_type>(__u & __sign_bit_mask ? ~__u : __u ^ __sign_bit_mask);
|
||||
}
|
||||
|
||||
// There may exist user-defined comparison for enum, so we cannot compare enums just like integers.
|
||||
template <class _Enum, enable_if_t< is_enum<_Enum>::value, int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral(_Enum __e) = delete;
|
||||
|
||||
// `long double` varies significantly across platforms and compilers, making it practically
|
||||
// impossible to determine its actual bit width for conversion to an ordered integer.
|
||||
inline _LIBCPP_HIDE_FROM_ABI constexpr auto __to_ordered_integral(long double) = delete;
|
||||
|
||||
template <class _Tp, class = void>
|
||||
inline const bool __is_ordered_integer_representable_v = false;
|
||||
|
||||
template <class _Tp>
|
||||
inline const bool
|
||||
__is_ordered_integer_representable_v<_Tp, __void_t<decltype(std::__to_ordered_integral(std::declval<_Tp>()))>> =
|
||||
true;
|
||||
|
||||
struct __low_byte_fn {
|
||||
template <class _Ip>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr uint8_t operator()(_Ip __integer) const {
|
||||
|
|
@ -307,18 +402,20 @@ struct __low_byte_fn {
|
|||
};
|
||||
|
||||
template <class _RandomAccessIterator1, class _RandomAccessIterator2, class _Map, class _Radix>
|
||||
_LIBCPP_HIDE_FROM_ABI void
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void
|
||||
__radix_sort(_RandomAccessIterator1 __first,
|
||||
_RandomAccessIterator1 __last,
|
||||
_RandomAccessIterator2 __buffer,
|
||||
_Map __map,
|
||||
_Radix __radix) {
|
||||
auto __map_to_unsigned = [__map = std::move(__map)](const auto& __x) { return std::__shift_to_unsigned(__map(__x)); };
|
||||
auto __map_to_unsigned = [__map = std::move(__map)](const auto& __x) {
|
||||
return std::__shift_to_unsigned(__map(std::__to_ordered_integral(__x)));
|
||||
};
|
||||
std::__radix_sort_impl(__first, __last, __buffer, __map_to_unsigned, __radix);
|
||||
}
|
||||
|
||||
template <class _RandomAccessIterator1, class _RandomAccessIterator2>
|
||||
_LIBCPP_HIDE_FROM_ABI void
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr void
|
||||
__radix_sort(_RandomAccessIterator1 __first, _RandomAccessIterator1 __last, _RandomAccessIterator2 __buffer) {
|
||||
std::__radix_sort(__first, __last, __buffer, __identity{}, __low_byte_fn{});
|
||||
}
|
||||
|
|
|
|||
18
lib/libcxx/include/__algorithm/ranges_for_each.h
vendored
18
lib/libcxx/include/__algorithm/ranges_for_each.h
vendored
|
|
@ -9,10 +9,12 @@
|
|||
#ifndef _LIBCPP___ALGORITHM_RANGES_FOR_EACH_H
|
||||
#define _LIBCPP___ALGORITHM_RANGES_FOR_EACH_H
|
||||
|
||||
#include <__algorithm/for_each.h>
|
||||
#include <__algorithm/for_each_n.h>
|
||||
#include <__algorithm/in_fun_result.h>
|
||||
#include <__concepts/assignable.h>
|
||||
#include <__config>
|
||||
#include <__functional/identity.h>
|
||||
#include <__functional/invoke.h>
|
||||
#include <__iterator/concepts.h>
|
||||
#include <__iterator/projected.h>
|
||||
#include <__ranges/access.h>
|
||||
|
|
@ -41,9 +43,17 @@ private:
|
|||
template <class _Iter, class _Sent, class _Proj, class _Func>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr static for_each_result<_Iter, _Func>
|
||||
__for_each_impl(_Iter __first, _Sent __last, _Func& __func, _Proj& __proj) {
|
||||
for (; __first != __last; ++__first)
|
||||
std::invoke(__func, std::invoke(__proj, *__first));
|
||||
return {std::move(__first), std::move(__func)};
|
||||
// In the case where we have different iterator and sentinel types, the segmented iterator optimization
|
||||
// in std::for_each will not kick in. Therefore, we prefer std::for_each_n in that case (whenever we can
|
||||
// obtain the `n`).
|
||||
if constexpr (!std::assignable_from<_Iter&, _Sent> && std::sized_sentinel_for<_Sent, _Iter>) {
|
||||
auto __n = __last - __first;
|
||||
auto __end = std::__for_each_n(std::move(__first), __n, __func, __proj);
|
||||
return {std::move(__end), std::move(__func)};
|
||||
} else {
|
||||
auto __end = std::__for_each(std::move(__first), std::move(__last), __func, __proj);
|
||||
return {std::move(__end), std::move(__func)};
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@
|
|||
#ifndef _LIBCPP___ALGORITHM_RANGES_FOR_EACH_N_H
|
||||
#define _LIBCPP___ALGORITHM_RANGES_FOR_EACH_N_H
|
||||
|
||||
#include <__algorithm/for_each_n.h>
|
||||
#include <__algorithm/in_fun_result.h>
|
||||
#include <__config>
|
||||
#include <__functional/identity.h>
|
||||
#include <__functional/invoke.h>
|
||||
#include <__iterator/concepts.h>
|
||||
#include <__iterator/incrementable_traits.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
|
|
@ -40,11 +40,8 @@ struct __for_each_n {
|
|||
template <input_iterator _Iter, class _Proj = identity, indirectly_unary_invocable<projected<_Iter, _Proj>> _Func>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr for_each_n_result<_Iter, _Func>
|
||||
operator()(_Iter __first, iter_difference_t<_Iter> __count, _Func __func, _Proj __proj = {}) const {
|
||||
while (__count-- > 0) {
|
||||
std::invoke(__func, std::invoke(__proj, *__first));
|
||||
++__first;
|
||||
}
|
||||
return {std::move(__first), std::move(__func)};
|
||||
auto __last = std::__for_each_n(std::move(__first), __count, __func, __proj);
|
||||
return {std::move(__last), std::move(__func)};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
namespace ranges {
|
||||
struct __inplace_merge {
|
||||
template <class _Iter, class _Sent, class _Comp, class _Proj>
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr auto
|
||||
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX26 auto
|
||||
__inplace_merge_impl(_Iter __first, _Iter __middle, _Sent __last, _Comp&& __comp, _Proj&& __proj) {
|
||||
auto __last_iter = ranges::next(__middle, __last);
|
||||
std::__inplace_merge<_RangeAlgPolicy>(
|
||||
|
|
@ -51,7 +51,7 @@ struct __inplace_merge {
|
|||
|
||||
template <bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity>
|
||||
requires sortable<_Iter, _Comp, _Proj>
|
||||
_LIBCPP_HIDE_FROM_ABI _Iter
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Iter
|
||||
operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
|
||||
return __inplace_merge_impl(
|
||||
std::move(__first), std::move(__middle), std::move(__last), std::move(__comp), std::move(__proj));
|
||||
|
|
@ -59,7 +59,7 @@ struct __inplace_merge {
|
|||
|
||||
template <bidirectional_range _Range, class _Comp = ranges::less, class _Proj = identity>
|
||||
requires sortable<iterator_t<_Range>, _Comp, _Proj>
|
||||
_LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 borrowed_iterator_t<_Range>
|
||||
operator()(_Range&& __range, iterator_t<_Range> __middle, _Comp __comp = {}, _Proj __proj = {}) const {
|
||||
return __inplace_merge_impl(
|
||||
ranges::begin(__range), std::move(__middle), ranges::end(__range), std::move(__comp), std::move(__proj));
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ consteval auto __get_iterator_concept() {
|
|||
}
|
||||
|
||||
template <class _Iter>
|
||||
using __iterator_concept _LIBCPP_NODEBUG = decltype(__get_iterator_concept<_Iter>());
|
||||
using __iterator_concept _LIBCPP_NODEBUG = decltype(ranges::__get_iterator_concept<_Iter>());
|
||||
|
||||
} // namespace ranges
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
|
|
|||
6
lib/libcxx/include/__algorithm/ranges_max.h
vendored
6
lib/libcxx/include/__algorithm/ranges_max.h
vendored
|
|
@ -9,7 +9,7 @@
|
|||
#ifndef _LIBCPP___ALGORITHM_RANGES_MAX_H
|
||||
#define _LIBCPP___ALGORITHM_RANGES_MAX_H
|
||||
|
||||
#include <__algorithm/ranges_min_element.h>
|
||||
#include <__algorithm/min_element.h>
|
||||
#include <__assert>
|
||||
#include <__concepts/copyable.h>
|
||||
#include <__config>
|
||||
|
|
@ -57,7 +57,7 @@ struct __max {
|
|||
__il.begin() != __il.end(), "initializer_list must contain at least one element");
|
||||
|
||||
auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) -> bool { return std::invoke(__comp, __rhs, __lhs); };
|
||||
return *ranges::__min_element_impl(__il.begin(), __il.end(), __comp_lhs_rhs_swapped, __proj);
|
||||
return *std::__min_element(__il.begin(), __il.end(), __comp_lhs_rhs_swapped, __proj);
|
||||
}
|
||||
|
||||
template <input_range _Rp,
|
||||
|
|
@ -75,7 +75,7 @@ struct __max {
|
|||
auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) -> bool {
|
||||
return std::invoke(__comp, __rhs, __lhs);
|
||||
};
|
||||
return *ranges::__min_element_impl(std::move(__first), std::move(__last), __comp_lhs_rhs_swapped, __proj);
|
||||
return *std::__min_element(std::move(__first), std::move(__last), __comp_lhs_rhs_swapped, __proj);
|
||||
} else {
|
||||
range_value_t<_Rp> __result = *__first;
|
||||
while (++__first != __last) {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#ifndef _LIBCPP___ALGORITHM_RANGES_MAX_ELEMENT_H
|
||||
#define _LIBCPP___ALGORITHM_RANGES_MAX_ELEMENT_H
|
||||
|
||||
#include <__algorithm/ranges_min_element.h>
|
||||
#include <__algorithm/min_element.h>
|
||||
#include <__config>
|
||||
#include <__functional/identity.h>
|
||||
#include <__functional/invoke.h>
|
||||
|
|
@ -40,7 +40,7 @@ struct __max_element {
|
|||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip
|
||||
operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const {
|
||||
auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) -> bool { return std::invoke(__comp, __rhs, __lhs); };
|
||||
return ranges::__min_element_impl(__first, __last, __comp_lhs_rhs_swapped, __proj);
|
||||
return std::__min_element(__first, __last, __comp_lhs_rhs_swapped, __proj);
|
||||
}
|
||||
|
||||
template <forward_range _Rp,
|
||||
|
|
@ -49,7 +49,7 @@ struct __max_element {
|
|||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp>
|
||||
operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const {
|
||||
auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) -> bool { return std::invoke(__comp, __rhs, __lhs); };
|
||||
return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp_lhs_rhs_swapped, __proj);
|
||||
return std::__min_element(ranges::begin(__r), ranges::end(__r), __comp_lhs_rhs_swapped, __proj);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
6
lib/libcxx/include/__algorithm/ranges_min.h
vendored
6
lib/libcxx/include/__algorithm/ranges_min.h
vendored
|
|
@ -9,7 +9,7 @@
|
|||
#ifndef _LIBCPP___ALGORITHM_RANGES_MIN_H
|
||||
#define _LIBCPP___ALGORITHM_RANGES_MIN_H
|
||||
|
||||
#include <__algorithm/ranges_min_element.h>
|
||||
#include <__algorithm/min_element.h>
|
||||
#include <__assert>
|
||||
#include <__concepts/copyable.h>
|
||||
#include <__config>
|
||||
|
|
@ -54,7 +54,7 @@ struct __min {
|
|||
operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const {
|
||||
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
|
||||
__il.begin() != __il.end(), "initializer_list must contain at least one element");
|
||||
return *ranges::__min_element_impl(__il.begin(), __il.end(), __comp, __proj);
|
||||
return *std::__min_element(__il.begin(), __il.end(), __comp, __proj);
|
||||
}
|
||||
|
||||
template <input_range _Rp,
|
||||
|
|
@ -67,7 +67,7 @@ struct __min {
|
|||
auto __last = ranges::end(__r);
|
||||
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__first != __last, "range must contain at least one element");
|
||||
if constexpr (forward_range<_Rp> && !__is_cheap_to_copy<range_value_t<_Rp>>) {
|
||||
return *ranges::__min_element_impl(__first, __last, __comp, __proj);
|
||||
return *std::__min_element(__first, __last, __comp, __proj);
|
||||
} else {
|
||||
range_value_t<_Rp> __result = *__first;
|
||||
while (++__first != __last) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#ifndef _LIBCPP___ALGORITHM_RANGES_MIN_ELEMENT_H
|
||||
#define _LIBCPP___ALGORITHM_RANGES_MIN_ELEMENT_H
|
||||
|
||||
#include <__algorithm/min_element.h>
|
||||
#include <__config>
|
||||
#include <__functional/identity.h>
|
||||
#include <__functional/invoke.h>
|
||||
|
|
@ -32,20 +33,6 @@ _LIBCPP_PUSH_MACROS
|
|||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
namespace ranges {
|
||||
|
||||
// TODO(ranges): `ranges::min_element` can now simply delegate to `std::__min_element`.
|
||||
template <class _Ip, class _Sp, class _Proj, class _Comp>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Ip __min_element_impl(_Ip __first, _Sp __last, _Comp& __comp, _Proj& __proj) {
|
||||
if (__first == __last)
|
||||
return __first;
|
||||
|
||||
_Ip __i = __first;
|
||||
while (++__i != __last)
|
||||
if (std::invoke(__comp, std::invoke(__proj, *__i), std::invoke(__proj, *__first)))
|
||||
__first = __i;
|
||||
return __first;
|
||||
}
|
||||
|
||||
struct __min_element {
|
||||
template <forward_iterator _Ip,
|
||||
sentinel_for<_Ip> _Sp,
|
||||
|
|
@ -53,7 +40,7 @@ struct __min_element {
|
|||
indirect_strict_weak_order<projected<_Ip, _Proj>> _Comp = ranges::less>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Ip
|
||||
operator()(_Ip __first, _Sp __last, _Comp __comp = {}, _Proj __proj = {}) const {
|
||||
return ranges::__min_element_impl(__first, __last, __comp, __proj);
|
||||
return std::__min_element(__first, __last, __comp, __proj);
|
||||
}
|
||||
|
||||
template <forward_range _Rp,
|
||||
|
|
@ -61,7 +48,7 @@ struct __min_element {
|
|||
indirect_strict_weak_order<projected<iterator_t<_Rp>, _Proj>> _Comp = ranges::less>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr borrowed_iterator_t<_Rp>
|
||||
operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const {
|
||||
return ranges::__min_element_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj);
|
||||
return std::__min_element(ranges::begin(__r), ranges::end(__r), __comp, __proj);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
namespace ranges {
|
||||
struct __stable_partition {
|
||||
template <class _Iter, class _Sent, class _Proj, class _Pred>
|
||||
_LIBCPP_HIDE_FROM_ABI static subrange<__remove_cvref_t<_Iter>>
|
||||
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX26 subrange<__remove_cvref_t<_Iter>>
|
||||
__stable_partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) {
|
||||
auto __last_iter = ranges::next(__first, __last);
|
||||
|
||||
|
|
@ -60,7 +60,8 @@ struct __stable_partition {
|
|||
class _Proj = identity,
|
||||
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
|
||||
requires permutable<_Iter>
|
||||
_LIBCPP_HIDE_FROM_ABI subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 subrange<_Iter>
|
||||
operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const {
|
||||
return __stable_partition_fn_impl(__first, __last, __pred, __proj);
|
||||
}
|
||||
|
||||
|
|
@ -68,7 +69,7 @@ struct __stable_partition {
|
|||
class _Proj = identity,
|
||||
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
|
||||
requires permutable<iterator_t<_Range>>
|
||||
_LIBCPP_HIDE_FROM_ABI borrowed_subrange_t<_Range>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 borrowed_subrange_t<_Range>
|
||||
operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const {
|
||||
return __stable_partition_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,8 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
namespace ranges {
|
||||
struct __stable_sort {
|
||||
template <class _Iter, class _Sent, class _Comp, class _Proj>
|
||||
_LIBCPP_HIDE_FROM_ABI static _Iter __stable_sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
|
||||
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX26 _Iter
|
||||
__stable_sort_fn_impl(_Iter __first, _Sent __last, _Comp& __comp, _Proj& __proj) {
|
||||
auto __last_iter = ranges::next(__first, __last);
|
||||
|
||||
auto&& __projected_comp = std::__make_projected(__comp, __proj);
|
||||
|
|
@ -52,13 +53,14 @@ struct __stable_sort {
|
|||
|
||||
template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Comp = ranges::less, class _Proj = identity>
|
||||
requires sortable<_Iter, _Comp, _Proj>
|
||||
_LIBCPP_HIDE_FROM_ABI _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _Iter
|
||||
operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const {
|
||||
return __stable_sort_fn_impl(std::move(__first), std::move(__last), __comp, __proj);
|
||||
}
|
||||
|
||||
template <random_access_range _Range, class _Comp = ranges::less, class _Proj = identity>
|
||||
requires sortable<iterator_t<_Range>, _Comp, _Proj>
|
||||
_LIBCPP_HIDE_FROM_ABI borrowed_iterator_t<_Range>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 borrowed_iterator_t<_Range>
|
||||
operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const {
|
||||
return __stable_sort_fn_impl(ranges::begin(__r), ranges::end(__r), __comp, __proj);
|
||||
}
|
||||
|
|
|
|||
45
lib/libcxx/include/__algorithm/rotate.h
vendored
45
lib/libcxx/include/__algorithm/rotate.h
vendored
|
|
@ -9,12 +9,19 @@
|
|||
#ifndef _LIBCPP___ALGORITHM_ROTATE_H
|
||||
#define _LIBCPP___ALGORITHM_ROTATE_H
|
||||
|
||||
#include <__algorithm/copy.h>
|
||||
#include <__algorithm/copy_backward.h>
|
||||
#include <__algorithm/iterator_operations.h>
|
||||
#include <__algorithm/move.h>
|
||||
#include <__algorithm/move_backward.h>
|
||||
#include <__algorithm/swap_ranges.h>
|
||||
#include <__config>
|
||||
#include <__cstddef/size_t.h>
|
||||
#include <__fwd/bit_reference.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__memory/construct_at.h>
|
||||
#include <__memory/pointer_traits.h>
|
||||
#include <__type_traits/is_constant_evaluated.h>
|
||||
#include <__type_traits/is_trivially_assignable.h>
|
||||
#include <__utility/move.h>
|
||||
#include <__utility/pair.h>
|
||||
|
|
@ -185,6 +192,44 @@ __rotate(_Iterator __first, _Iterator __middle, _Sentinel __last) {
|
|||
return _Ret(std::move(__result), std::move(__last_iter));
|
||||
}
|
||||
|
||||
template <class, class _Cp>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cp, false>, __bit_iterator<_Cp, false> >
|
||||
__rotate(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __middle, __bit_iterator<_Cp, false> __last) {
|
||||
using _I1 = __bit_iterator<_Cp, false>;
|
||||
using difference_type = typename _I1::difference_type;
|
||||
difference_type __d1 = __middle - __first;
|
||||
difference_type __d2 = __last - __middle;
|
||||
_I1 __r = __first + __d2;
|
||||
while (__d1 != 0 && __d2 != 0) {
|
||||
if (__d1 <= __d2) {
|
||||
if (__d1 <= __bit_array<_Cp>::capacity()) {
|
||||
__bit_array<_Cp> __b(__d1);
|
||||
std::copy(__first, __middle, __b.begin());
|
||||
std::copy(__b.begin(), __b.end(), std::copy(__middle, __last, __first));
|
||||
break;
|
||||
} else {
|
||||
__bit_iterator<_Cp, false> __mp = std::swap_ranges(__first, __middle, __middle);
|
||||
__first = __middle;
|
||||
__middle = __mp;
|
||||
__d2 -= __d1;
|
||||
}
|
||||
} else {
|
||||
if (__d2 <= __bit_array<_Cp>::capacity()) {
|
||||
__bit_array<_Cp> __b(__d2);
|
||||
std::copy(__middle, __last, __b.begin());
|
||||
std::copy_backward(__b.begin(), __b.end(), std::copy_backward(__first, __middle, __last));
|
||||
break;
|
||||
} else {
|
||||
__bit_iterator<_Cp, false> __mp = __first + __d2;
|
||||
std::swap_ranges(__first, __mp, __middle);
|
||||
__first = __mp;
|
||||
__d1 -= __d2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::make_pair(__r, __last);
|
||||
}
|
||||
|
||||
template <class _ForwardIterator>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator
|
||||
rotate(_ForwardIterator __first, _ForwardIterator __middle, _ForwardIterator __last) {
|
||||
|
|
|
|||
16
lib/libcxx/include/__algorithm/simd_utils.h
vendored
16
lib/libcxx/include/__algorithm/simd_utils.h
vendored
|
|
@ -15,8 +15,6 @@
|
|||
#include <__bit/countr.h>
|
||||
#include <__config>
|
||||
#include <__cstddef/size_t.h>
|
||||
#include <__type_traits/is_arithmetic.h>
|
||||
#include <__type_traits/is_same.h>
|
||||
#include <__utility/integer_sequence.h>
|
||||
#include <cstdint>
|
||||
|
||||
|
|
@ -28,7 +26,9 @@ _LIBCPP_PUSH_MACROS
|
|||
#include <__undef_macros>
|
||||
|
||||
// TODO: Find out how altivec changes things and allow vectorizations there too.
|
||||
#if _LIBCPP_STD_VER >= 14 && defined(_LIBCPP_CLANG_VER) && !defined(__ALTIVEC__)
|
||||
// TODO: Simplify this condition once we stop building with AppleClang 15 in the CI.
|
||||
#if _LIBCPP_STD_VER >= 14 && defined(_LIBCPP_COMPILER_CLANG_BASED) && !defined(__ALTIVEC__) && \
|
||||
!(defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 1600)
|
||||
# define _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS 1
|
||||
#else
|
||||
# define _LIBCPP_HAS_ALGORITHM_VECTOR_UTILS 0
|
||||
|
|
@ -53,20 +53,20 @@ struct __get_as_integer_type_impl;
|
|||
|
||||
template <>
|
||||
struct __get_as_integer_type_impl<1> {
|
||||
using type = uint8_t;
|
||||
using type _LIBCPP_NODEBUG = uint8_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct __get_as_integer_type_impl<2> {
|
||||
using type = uint16_t;
|
||||
using type _LIBCPP_NODEBUG = uint16_t;
|
||||
};
|
||||
template <>
|
||||
struct __get_as_integer_type_impl<4> {
|
||||
using type = uint32_t;
|
||||
using type _LIBCPP_NODEBUG = uint32_t;
|
||||
};
|
||||
template <>
|
||||
struct __get_as_integer_type_impl<8> {
|
||||
using type = uint64_t;
|
||||
using type _LIBCPP_NODEBUG = uint64_t;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
|
|
@ -78,7 +78,7 @@ using __get_as_integer_type_t _LIBCPP_NODEBUG = typename __get_as_integer_type_i
|
|||
# if defined(__AVX__) || defined(__MVS__)
|
||||
template <class _Tp>
|
||||
inline constexpr size_t __native_vector_size = 32 / sizeof(_Tp);
|
||||
# elif defined(__SSE__) || defined(__ARM_NEON__)
|
||||
# elif defined(__SSE__) || defined(__ARM_NEON)
|
||||
template <class _Tp>
|
||||
inline constexpr size_t __native_vector_size = 16 / sizeof(_Tp);
|
||||
# elif defined(__MMX__)
|
||||
|
|
|
|||
39
lib/libcxx/include/__algorithm/sort.h
vendored
39
lib/libcxx/include/__algorithm/sort.h
vendored
|
|
@ -17,6 +17,7 @@
|
|||
#include <__algorithm/partial_sort.h>
|
||||
#include <__algorithm/unwrap_iter.h>
|
||||
#include <__assert>
|
||||
#include <__bit/bit_log2.h>
|
||||
#include <__bit/blsr.h>
|
||||
#include <__bit/countl.h>
|
||||
#include <__bit/countr.h>
|
||||
|
|
@ -34,7 +35,7 @@
|
|||
#include <__type_traits/is_constant_evaluated.h>
|
||||
#include <__type_traits/is_same.h>
|
||||
#include <__type_traits/is_trivially_copyable.h>
|
||||
#include <__type_traits/remove_cvref.h>
|
||||
#include <__type_traits/make_unsigned.h>
|
||||
#include <__utility/move.h>
|
||||
#include <__utility/pair.h>
|
||||
#include <climits>
|
||||
|
|
@ -52,8 +53,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
template <class _Compare, class _Iter, class _Tp = typename iterator_traits<_Iter>::value_type>
|
||||
inline const bool __use_branchless_sort =
|
||||
__libcpp_is_contiguous_iterator<_Iter>::value && __is_cheap_to_copy<_Tp> && is_arithmetic<_Tp>::value &&
|
||||
(__desugars_to_v<__less_tag, __remove_cvref_t<_Compare>, _Tp, _Tp> ||
|
||||
__desugars_to_v<__greater_tag, __remove_cvref_t<_Compare>, _Tp, _Tp>);
|
||||
(__desugars_to_v<__less_tag, _Compare, _Tp, _Tp> || __desugars_to_v<__greater_tag, _Compare, _Tp, _Tp>);
|
||||
|
||||
namespace __detail {
|
||||
|
||||
|
|
@ -359,10 +359,10 @@ inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos(
|
|||
// Swap one pair on each iteration as long as both bitsets have at least one
|
||||
// element for swapping.
|
||||
while (__left_bitset != 0 && __right_bitset != 0) {
|
||||
difference_type __tz_left = __libcpp_ctz(__left_bitset);
|
||||
__left_bitset = __libcpp_blsr(__left_bitset);
|
||||
difference_type __tz_right = __libcpp_ctz(__right_bitset);
|
||||
__right_bitset = __libcpp_blsr(__right_bitset);
|
||||
difference_type __tz_left = std::__countr_zero(__left_bitset);
|
||||
__left_bitset = std::__libcpp_blsr(__left_bitset);
|
||||
difference_type __tz_right = std::__countr_zero(__right_bitset);
|
||||
__right_bitset = std::__libcpp_blsr(__right_bitset);
|
||||
_Ops::iter_swap(__first + __tz_left, __last - __tz_right);
|
||||
}
|
||||
}
|
||||
|
|
@ -458,7 +458,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within(
|
|||
// Swap within the left side. Need to find set positions in the reverse
|
||||
// order.
|
||||
while (__left_bitset != 0) {
|
||||
difference_type __tz_left = __detail::__block_size - 1 - __libcpp_clz(__left_bitset);
|
||||
difference_type __tz_left = __detail::__block_size - 1 - std::__countl_zero(__left_bitset);
|
||||
__left_bitset &= (static_cast<uint64_t>(1) << __tz_left) - 1;
|
||||
_RandomAccessIterator __it = __first + __tz_left;
|
||||
if (__it != __lm1) {
|
||||
|
|
@ -471,7 +471,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within(
|
|||
// Swap within the right side. Need to find set positions in the reverse
|
||||
// order.
|
||||
while (__right_bitset != 0) {
|
||||
difference_type __tz_right = __detail::__block_size - 1 - __libcpp_clz(__right_bitset);
|
||||
difference_type __tz_right = __detail::__block_size - 1 - std::__countl_zero(__right_bitset);
|
||||
__right_bitset &= (static_cast<uint64_t>(1) << __tz_right) - 1;
|
||||
_RandomAccessIterator __it = __lm1 - __tz_right;
|
||||
if (__it != __first) {
|
||||
|
|
@ -828,25 +828,6 @@ void __introsort(_RandomAccessIterator __first,
|
|||
}
|
||||
}
|
||||
|
||||
template <typename _Number>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _Number __log2i(_Number __n) {
|
||||
if (__n == 0)
|
||||
return 0;
|
||||
if (sizeof(__n) <= sizeof(unsigned))
|
||||
return sizeof(unsigned) * CHAR_BIT - 1 - __libcpp_clz(static_cast<unsigned>(__n));
|
||||
if (sizeof(__n) <= sizeof(unsigned long))
|
||||
return sizeof(unsigned long) * CHAR_BIT - 1 - __libcpp_clz(static_cast<unsigned long>(__n));
|
||||
if (sizeof(__n) <= sizeof(unsigned long long))
|
||||
return sizeof(unsigned long long) * CHAR_BIT - 1 - __libcpp_clz(static_cast<unsigned long long>(__n));
|
||||
|
||||
_Number __log2 = 0;
|
||||
while (__n > 1) {
|
||||
__log2++;
|
||||
__n >>= 1;
|
||||
}
|
||||
return __log2;
|
||||
}
|
||||
|
||||
template <class _Comp, class _RandomAccessIterator>
|
||||
void __sort(_RandomAccessIterator, _RandomAccessIterator, _Comp);
|
||||
|
||||
|
|
@ -880,7 +861,7 @@ template <class _AlgPolicy, class _RandomAccessIterator, class _Comp>
|
|||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
|
||||
__sort_dispatch(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) {
|
||||
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
|
||||
difference_type __depth_limit = 2 * std::__log2i(__last - __first);
|
||||
difference_type __depth_limit = 2 * std::__bit_log2(std::__to_unsigned_like(__last - __first));
|
||||
|
||||
// Only use bitset partitioning for arithmetic types. We should also check
|
||||
// that the default comparator is in use so that we are sure that there are no
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
#include <__iterator/advance.h>
|
||||
#include <__iterator/distance.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__memory/construct_at.h>
|
||||
#include <__memory/destruct_n.h>
|
||||
#include <__memory/unique_ptr.h>
|
||||
#include <__memory/unique_temporary_buffer.h>
|
||||
|
|
@ -33,7 +34,7 @@ _LIBCPP_PUSH_MACROS
|
|||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _Distance, class _Pair>
|
||||
_LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition_impl(
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator __stable_partition_impl(
|
||||
_ForwardIterator __first,
|
||||
_ForwardIterator __last,
|
||||
_Predicate __pred,
|
||||
|
|
@ -61,7 +62,7 @@ _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition_impl(
|
|||
// Move the falses into the temporary buffer, and the trues to the front of the line
|
||||
// Update __first to always point to the end of the trues
|
||||
value_type* __t = __p.first;
|
||||
::new ((void*)__t) value_type(_Ops::__iter_move(__first));
|
||||
std::__construct_at(__t, _Ops::__iter_move(__first));
|
||||
__d.template __incr<value_type>();
|
||||
++__t;
|
||||
_ForwardIterator __i = __first;
|
||||
|
|
@ -70,7 +71,7 @@ _LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition_impl(
|
|||
*__first = _Ops::__iter_move(__i);
|
||||
++__first;
|
||||
} else {
|
||||
::new ((void*)__t) value_type(_Ops::__iter_move(__i));
|
||||
std::__construct_at(__t, _Ops::__iter_move(__i));
|
||||
__d.template __incr<value_type>();
|
||||
++__t;
|
||||
}
|
||||
|
|
@ -116,7 +117,7 @@ __second_half_done:
|
|||
}
|
||||
|
||||
template <class _AlgPolicy, class _Predicate, class _ForwardIterator>
|
||||
_LIBCPP_HIDE_FROM_ABI _ForwardIterator
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
|
||||
__stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, forward_iterator_tag) {
|
||||
typedef typename iterator_traits<_ForwardIterator>::difference_type difference_type;
|
||||
typedef typename iterator_traits<_ForwardIterator>::value_type value_type;
|
||||
|
|
@ -145,7 +146,7 @@ __stable_partition_impl(_ForwardIterator __first, _ForwardIterator __last, _Pred
|
|||
}
|
||||
|
||||
template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator, class _Distance, class _Pair>
|
||||
_BidirectionalIterator __stable_partition_impl(
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX26 _BidirectionalIterator __stable_partition_impl(
|
||||
_BidirectionalIterator __first,
|
||||
_BidirectionalIterator __last,
|
||||
_Predicate __pred,
|
||||
|
|
@ -179,7 +180,7 @@ _BidirectionalIterator __stable_partition_impl(
|
|||
// Move the falses into the temporary buffer, and the trues to the front of the line
|
||||
// Update __first to always point to the end of the trues
|
||||
value_type* __t = __p.first;
|
||||
::new ((void*)__t) value_type(_Ops::__iter_move(__first));
|
||||
std::__construct_at(__t, _Ops::__iter_move(__first));
|
||||
__d.template __incr<value_type>();
|
||||
++__t;
|
||||
_BidirectionalIterator __i = __first;
|
||||
|
|
@ -188,7 +189,7 @@ _BidirectionalIterator __stable_partition_impl(
|
|||
*__first = _Ops::__iter_move(__i);
|
||||
++__first;
|
||||
} else {
|
||||
::new ((void*)__t) value_type(_Ops::__iter_move(__i));
|
||||
std::__construct_at(__t, _Ops::__iter_move(__i));
|
||||
__d.template __incr<value_type>();
|
||||
++__t;
|
||||
}
|
||||
|
|
@ -247,7 +248,7 @@ __second_half_done:
|
|||
}
|
||||
|
||||
template <class _AlgPolicy, class _Predicate, class _BidirectionalIterator>
|
||||
_LIBCPP_HIDE_FROM_ABI _BidirectionalIterator __stable_partition_impl(
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _BidirectionalIterator __stable_partition_impl(
|
||||
_BidirectionalIterator __first, _BidirectionalIterator __last, _Predicate __pred, bidirectional_iterator_tag) {
|
||||
typedef typename iterator_traits<_BidirectionalIterator>::difference_type difference_type;
|
||||
typedef typename iterator_traits<_BidirectionalIterator>::value_type value_type;
|
||||
|
|
@ -283,14 +284,14 @@ _LIBCPP_HIDE_FROM_ABI _BidirectionalIterator __stable_partition_impl(
|
|||
}
|
||||
|
||||
template <class _AlgPolicy, class _Predicate, class _ForwardIterator, class _IterCategory>
|
||||
_LIBCPP_HIDE_FROM_ABI _ForwardIterator __stable_partition(
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator __stable_partition(
|
||||
_ForwardIterator __first, _ForwardIterator __last, _Predicate&& __pred, _IterCategory __iter_category) {
|
||||
return std::__stable_partition_impl<_AlgPolicy, __remove_cvref_t<_Predicate>&>(
|
||||
std::move(__first), std::move(__last), __pred, __iter_category);
|
||||
}
|
||||
|
||||
template <class _ForwardIterator, class _Predicate>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _ForwardIterator
|
||||
_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX26 _ForwardIterator
|
||||
stable_partition(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred) {
|
||||
using _IterCategory = typename iterator_traits<_ForwardIterator>::iterator_category;
|
||||
return std::__stable_partition<_ClassicAlgPolicy, _Predicate&>(
|
||||
|
|
|
|||
28
lib/libcxx/include/__algorithm/stable_sort.h
vendored
28
lib/libcxx/include/__algorithm/stable_sort.h
vendored
|
|
@ -25,10 +25,9 @@
|
|||
#include <__memory/unique_temporary_buffer.h>
|
||||
#include <__type_traits/desugars_to.h>
|
||||
#include <__type_traits/enable_if.h>
|
||||
#include <__type_traits/is_integral.h>
|
||||
#include <__type_traits/is_constant_evaluated.h>
|
||||
#include <__type_traits/is_same.h>
|
||||
#include <__type_traits/is_trivially_assignable.h>
|
||||
#include <__type_traits/remove_cvref.h>
|
||||
#include <__utility/move.h>
|
||||
#include <__utility/pair.h>
|
||||
|
||||
|
|
@ -201,7 +200,7 @@ struct __stable_sort_switch {
|
|||
#if _LIBCPP_STD_VER >= 17
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr unsigned __radix_sort_min_bound() {
|
||||
static_assert(is_integral<_Tp>::value);
|
||||
static_assert(__is_ordered_integer_representable_v<_Tp>);
|
||||
if constexpr (sizeof(_Tp) == 1) {
|
||||
return 1 << 8;
|
||||
}
|
||||
|
|
@ -211,7 +210,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr unsigned __radix_sort_min_bound() {
|
|||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr unsigned __radix_sort_max_bound() {
|
||||
static_assert(is_integral<_Tp>::value);
|
||||
static_assert(__is_ordered_integer_representable_v<_Tp>);
|
||||
if constexpr (sizeof(_Tp) >= 8) {
|
||||
return 1 << 15;
|
||||
}
|
||||
|
|
@ -245,14 +244,19 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort(
|
|||
}
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
constexpr auto __default_comp =
|
||||
__desugars_to_v<__totally_ordered_less_tag, __remove_cvref_t<_Compare>, value_type, value_type >;
|
||||
constexpr auto __integral_value =
|
||||
is_integral_v<value_type > && is_same_v< value_type&, __iter_reference<_RandomAccessIterator>>;
|
||||
constexpr auto __allowed_radix_sort = __default_comp && __integral_value;
|
||||
if constexpr (__allowed_radix_sort) {
|
||||
if (__len <= __buff_size && __len >= static_cast<difference_type>(__radix_sort_min_bound<value_type>()) &&
|
||||
__len <= static_cast<difference_type>(__radix_sort_max_bound<value_type>())) {
|
||||
constexpr auto __default_comp = __desugars_to_v<__less_tag, _Compare, value_type, value_type >;
|
||||
constexpr auto __radix_sortable =
|
||||
__is_ordered_integer_representable_v<value_type> &&
|
||||
is_same_v< value_type&, __iter_reference<_RandomAccessIterator>>;
|
||||
if constexpr (__default_comp && __radix_sortable) {
|
||||
if (__len <= __buff_size && __len >= static_cast<difference_type>(std::__radix_sort_min_bound<value_type>()) &&
|
||||
__len <= static_cast<difference_type>(std::__radix_sort_max_bound<value_type>())) {
|
||||
if (__libcpp_is_constant_evaluated()) {
|
||||
for (auto* __p = __buff; __p < __buff + __buff_size; ++__p) {
|
||||
std::__construct_at(__p);
|
||||
}
|
||||
}
|
||||
|
||||
std::__radix_sort(__first, __last, __buff);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
162
lib/libcxx/include/__algorithm/swap_ranges.h
vendored
162
lib/libcxx/include/__algorithm/swap_ranges.h
vendored
|
|
@ -10,9 +10,12 @@
|
|||
#define _LIBCPP___ALGORITHM_SWAP_RANGES_H
|
||||
|
||||
#include <__algorithm/iterator_operations.h>
|
||||
#include <__algorithm/min.h>
|
||||
#include <__config>
|
||||
#include <__fwd/bit_reference.h>
|
||||
#include <__utility/move.h>
|
||||
#include <__utility/pair.h>
|
||||
#include <__utility/swap.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
|
|
@ -23,6 +26,165 @@ _LIBCPP_PUSH_MACROS
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class _Cl, class _Cr>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cr, false> __swap_ranges_aligned(
|
||||
__bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) {
|
||||
using _I1 = __bit_iterator<_Cl, false>;
|
||||
using difference_type = typename _I1::difference_type;
|
||||
using __storage_type = typename _I1::__storage_type;
|
||||
|
||||
const int __bits_per_word = _I1::__bits_per_word;
|
||||
difference_type __n = __last - __first;
|
||||
if (__n > 0) {
|
||||
// do first word
|
||||
if (__first.__ctz_ != 0) {
|
||||
unsigned __clz = __bits_per_word - __first.__ctz_;
|
||||
difference_type __dn = std::min(static_cast<difference_type>(__clz), __n);
|
||||
__n -= __dn;
|
||||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn));
|
||||
__storage_type __b1 = *__first.__seg_ & __m;
|
||||
*__first.__seg_ &= ~__m;
|
||||
__storage_type __b2 = *__result.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b1;
|
||||
*__first.__seg_ |= __b2;
|
||||
__result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
|
||||
__result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
|
||||
++__first.__seg_;
|
||||
// __first.__ctz_ = 0;
|
||||
}
|
||||
// __first.__ctz_ == 0;
|
||||
// do middle words
|
||||
for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_, ++__result.__seg_)
|
||||
swap(*__first.__seg_, *__result.__seg_);
|
||||
// do last word
|
||||
if (__n > 0) {
|
||||
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__storage_type __b1 = *__first.__seg_ & __m;
|
||||
*__first.__seg_ &= ~__m;
|
||||
__storage_type __b2 = *__result.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b1;
|
||||
*__first.__seg_ |= __b2;
|
||||
__result.__ctz_ = static_cast<unsigned>(__n);
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _Cl, class _Cr>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cr, false> __swap_ranges_unaligned(
|
||||
__bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) {
|
||||
using _I1 = __bit_iterator<_Cl, false>;
|
||||
using difference_type = typename _I1::difference_type;
|
||||
using __storage_type = typename _I1::__storage_type;
|
||||
|
||||
const int __bits_per_word = _I1::__bits_per_word;
|
||||
difference_type __n = __last - __first;
|
||||
if (__n > 0) {
|
||||
// do first word
|
||||
if (__first.__ctz_ != 0) {
|
||||
unsigned __clz_f = __bits_per_word - __first.__ctz_;
|
||||
difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n);
|
||||
__n -= __dn;
|
||||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
|
||||
__storage_type __b1 = *__first.__seg_ & __m;
|
||||
*__first.__seg_ &= ~__m;
|
||||
unsigned __clz_r = __bits_per_word - __result.__ctz_;
|
||||
__storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
|
||||
__m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn));
|
||||
__storage_type __b2 = *__result.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
if (__result.__ctz_ > __first.__ctz_) {
|
||||
unsigned __s = __result.__ctz_ - __first.__ctz_;
|
||||
*__result.__seg_ |= __b1 << __s;
|
||||
*__first.__seg_ |= __b2 >> __s;
|
||||
} else {
|
||||
unsigned __s = __first.__ctz_ - __result.__ctz_;
|
||||
*__result.__seg_ |= __b1 >> __s;
|
||||
*__first.__seg_ |= __b2 << __s;
|
||||
}
|
||||
__result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word;
|
||||
__result.__ctz_ = static_cast<unsigned>((__ddn + __result.__ctz_) % __bits_per_word);
|
||||
__dn -= __ddn;
|
||||
if (__dn > 0) {
|
||||
__m = ~__storage_type(0) >> (__bits_per_word - __dn);
|
||||
__b2 = *__result.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
unsigned __s = __first.__ctz_ + __ddn;
|
||||
*__result.__seg_ |= __b1 >> __s;
|
||||
*__first.__seg_ |= __b2 << __s;
|
||||
__result.__ctz_ = static_cast<unsigned>(__dn);
|
||||
}
|
||||
++__first.__seg_;
|
||||
// __first.__ctz_ = 0;
|
||||
}
|
||||
// __first.__ctz_ == 0;
|
||||
// do middle words
|
||||
__storage_type __m = ~__storage_type(0) << __result.__ctz_;
|
||||
unsigned __clz_r = __bits_per_word - __result.__ctz_;
|
||||
for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) {
|
||||
__storage_type __b1 = *__first.__seg_;
|
||||
__storage_type __b2 = *__result.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b1 << __result.__ctz_;
|
||||
*__first.__seg_ = __b2 >> __result.__ctz_;
|
||||
++__result.__seg_;
|
||||
__b2 = *__result.__seg_ & ~__m;
|
||||
*__result.__seg_ &= __m;
|
||||
*__result.__seg_ |= __b1 >> __clz_r;
|
||||
*__first.__seg_ |= __b2 << __clz_r;
|
||||
}
|
||||
// do last word
|
||||
if (__n > 0) {
|
||||
__m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__storage_type __b1 = *__first.__seg_ & __m;
|
||||
*__first.__seg_ &= ~__m;
|
||||
__storage_type __dn = std::min<__storage_type>(__n, __clz_r);
|
||||
__m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn));
|
||||
__storage_type __b2 = *__result.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b1 << __result.__ctz_;
|
||||
*__first.__seg_ |= __b2 >> __result.__ctz_;
|
||||
__result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
|
||||
__result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
|
||||
__n -= __dn;
|
||||
if (__n > 0) {
|
||||
__m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__b2 = *__result.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b1 >> __dn;
|
||||
*__first.__seg_ |= __b2 << __dn;
|
||||
__result.__ctz_ = static_cast<unsigned>(__n);
|
||||
}
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
// 2+1 iterators: size2 >= size1; used by std::swap_ranges.
|
||||
template <class, class _Cl, class _Cr>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cl, false>, __bit_iterator<_Cr, false> >
|
||||
__swap_ranges(__bit_iterator<_Cl, false> __first1,
|
||||
__bit_iterator<_Cl, false> __last1,
|
||||
__bit_iterator<_Cr, false> __first2) {
|
||||
if (__first1.__ctz_ == __first2.__ctz_)
|
||||
return std::make_pair(__last1, std::__swap_ranges_aligned(__first1, __last1, __first2));
|
||||
return std::make_pair(__last1, std::__swap_ranges_unaligned(__first1, __last1, __first2));
|
||||
}
|
||||
|
||||
// 2+2 iterators: used by std::ranges::swap_ranges.
|
||||
template <class _AlgPolicy, class _Cl, class _Cr>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<__bit_iterator<_Cl, false>, __bit_iterator<_Cr, false> >
|
||||
__swap_ranges(__bit_iterator<_Cl, false> __first1,
|
||||
__bit_iterator<_Cl, false> __last1,
|
||||
__bit_iterator<_Cr, false> __first2,
|
||||
__bit_iterator<_Cr, false> __last2) {
|
||||
if (__last1 - __first1 < __last2 - __first2)
|
||||
return std::make_pair(__last1, std::__swap_ranges<_AlgPolicy>(__first1, __last1, __first2).second);
|
||||
return std::make_pair(std::__swap_ranges<_AlgPolicy>(__first2, __last2, __first1).second, __last2);
|
||||
}
|
||||
|
||||
// 2+2 iterators: the shorter size will be used.
|
||||
template <class _AlgPolicy, class _ForwardIterator1, class _Sentinel1, class _ForwardIterator2, class _Sentinel2>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 pair<_ForwardIterator1, _ForwardIterator2>
|
||||
|
|
|
|||
4
lib/libcxx/include/__assert
vendored
4
lib/libcxx/include/__assert
vendored
|
|
@ -20,8 +20,8 @@
|
|||
#define _LIBCPP_ASSERT(expression, message) \
|
||||
(__builtin_expect(static_cast<bool>(expression), 1) \
|
||||
? (void)0 \
|
||||
: _LIBCPP_ASSERTION_HANDLER(__FILE__ ":" _LIBCPP_TOSTRING(__LINE__) ": assertion " _LIBCPP_TOSTRING( \
|
||||
expression) " failed: " message "\n"))
|
||||
: _LIBCPP_ASSERTION_HANDLER(__FILE__ ":" _LIBCPP_TOSTRING( \
|
||||
__LINE__) ": libc++ Hardening assertion " _LIBCPP_TOSTRING(expression) " failed: " message "\n"))
|
||||
|
||||
// WARNING: __builtin_assume can currently inhibit optimizations. Only add assumptions with a clear
|
||||
// optimization intent. See https://discourse.llvm.org/t/llvm-assume-blocks-optimization/71609 for a
|
||||
|
|
|
|||
15
lib/libcxx/include/__assertion_handler
vendored
15
lib/libcxx/include/__assertion_handler
vendored
|
|
@ -13,9 +13,11 @@
|
|||
#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
|
||||
# include <__cxx03/__config>
|
||||
# include <__cxx03/__verbose_abort>
|
||||
# include <__cxx03/__verbose_trap>
|
||||
#else
|
||||
# include <__config>
|
||||
# include <__verbose_abort>
|
||||
# include <__verbose_trap>
|
||||
#endif
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
|
|
@ -28,18 +30,7 @@
|
|||
|
||||
#else
|
||||
|
||||
# if __has_builtin(__builtin_verbose_trap)
|
||||
// AppleClang shipped a slightly different version of __builtin_verbose_trap from the upstream
|
||||
// version before upstream Clang actually got the builtin.
|
||||
// TODO: Remove once AppleClang supports the two-arguments version of the builtin.
|
||||
# if defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 1700
|
||||
# define _LIBCPP_ASSERTION_HANDLER(message) __builtin_verbose_trap(message)
|
||||
# else
|
||||
# define _LIBCPP_ASSERTION_HANDLER(message) __builtin_verbose_trap("libc++", message)
|
||||
# endif
|
||||
# else
|
||||
# define _LIBCPP_ASSERTION_HANDLER(message) ((void)message, __builtin_trap())
|
||||
# endif
|
||||
# define _LIBCPP_ASSERTION_HANDLER(message) _LIBCPP_VERBOSE_TRAP(message)
|
||||
|
||||
#endif // _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
|
||||
|
||||
|
|
|
|||
19
lib/libcxx/include/__atomic/atomic.h
vendored
19
lib/libcxx/include/__atomic/atomic.h
vendored
|
|
@ -23,6 +23,7 @@
|
|||
#include <__type_traits/is_integral.h>
|
||||
#include <__type_traits/is_nothrow_constructible.h>
|
||||
#include <__type_traits/is_same.h>
|
||||
#include <__type_traits/is_trivially_copyable.h>
|
||||
#include <__type_traits/remove_const.h>
|
||||
#include <__type_traits/remove_pointer.h>
|
||||
#include <__type_traits/remove_volatile.h>
|
||||
|
|
@ -40,6 +41,8 @@ struct __atomic_base // false
|
|||
{
|
||||
mutable __cxx_atomic_impl<_Tp> __a_;
|
||||
|
||||
using value_type = _Tp;
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
static constexpr bool is_always_lock_free = __libcpp_is_always_lock_free<__cxx_atomic_impl<_Tp> >::__value;
|
||||
#endif
|
||||
|
|
@ -145,6 +148,8 @@ template <class _Tp>
|
|||
struct __atomic_base<_Tp, true> : public __atomic_base<_Tp, false> {
|
||||
using __base _LIBCPP_NODEBUG = __atomic_base<_Tp, false>;
|
||||
|
||||
using difference_type = typename __base::value_type;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __atomic_base() _NOEXCEPT = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __atomic_base(_Tp __d) _NOEXCEPT : __base(__d) {}
|
||||
|
|
@ -226,11 +231,15 @@ struct __atomic_waitable_traits<__atomic_base<_Tp, _IsIntegral> > {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename _Tp>
|
||||
struct __check_atomic_mandates {
|
||||
using type _LIBCPP_NODEBUG = _Tp;
|
||||
static_assert(is_trivially_copyable<_Tp>::value, "std::atomic<T> requires that 'T' be a trivially copyable type");
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct atomic : public __atomic_base<_Tp> {
|
||||
struct atomic : public __atomic_base<typename __check_atomic_mandates<_Tp>::type> {
|
||||
using __base _LIBCPP_NODEBUG = __atomic_base<_Tp>;
|
||||
using value_type = _Tp;
|
||||
using difference_type = value_type;
|
||||
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
_LIBCPP_HIDE_FROM_ABI atomic() = default;
|
||||
|
|
@ -258,7 +267,7 @@ struct atomic : public __atomic_base<_Tp> {
|
|||
template <class _Tp>
|
||||
struct atomic<_Tp*> : public __atomic_base<_Tp*> {
|
||||
using __base _LIBCPP_NODEBUG = __atomic_base<_Tp*>;
|
||||
using value_type = _Tp*;
|
||||
|
||||
using difference_type = ptrdiff_t;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI atomic() _NOEXCEPT = default;
|
||||
|
|
@ -361,7 +370,7 @@ private:
|
|||
// https://github.com/llvm/llvm-project/issues/47978
|
||||
// clang bug: __old is not updated on failure for atomic<long double>::compare_exchange_weak
|
||||
// Note __old = __self.load(memory_order_relaxed) will not work
|
||||
std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), &__old, memory_order_relaxed);
|
||||
std::__cxx_atomic_load_inplace(std::addressof(__self.__a_), std::addressof(__old), memory_order_relaxed);
|
||||
}
|
||||
# endif
|
||||
__new = __operation(__old, __operand);
|
||||
|
|
|
|||
2
lib/libcxx/include/__atomic/atomic_ref.h
vendored
2
lib/libcxx/include/__atomic/atomic_ref.h
vendored
|
|
@ -119,7 +119,7 @@ public:
|
|||
// that the pointer is going to be aligned properly at runtime because that is a (checked) precondition
|
||||
// of atomic_ref's constructor.
|
||||
static constexpr bool is_always_lock_free =
|
||||
__atomic_always_lock_free(sizeof(_Tp), &__get_aligner_instance<required_alignment>::__instance);
|
||||
__atomic_always_lock_free(sizeof(_Tp), std::addressof(__get_aligner_instance<required_alignment>::__instance));
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI bool is_lock_free() const noexcept { return __atomic_is_lock_free(sizeof(_Tp), __ptr_); }
|
||||
|
||||
|
|
|
|||
4
lib/libcxx/include/__atomic/memory_order.h
vendored
4
lib/libcxx/include/__atomic/memory_order.h
vendored
|
|
@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
// to pin the underlying type in C++20.
|
||||
enum __legacy_memory_order { __mo_relaxed, __mo_consume, __mo_acquire, __mo_release, __mo_acq_rel, __mo_seq_cst };
|
||||
|
||||
using __memory_order_underlying_t _LIBCPP_NODEBUG = underlying_type<__legacy_memory_order>::type;
|
||||
using __memory_order_underlying_t _LIBCPP_NODEBUG = __underlying_type_t<__legacy_memory_order>;
|
||||
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ enum class memory_order : __memory_order_underlying_t {
|
|||
seq_cst = __mo_seq_cst
|
||||
};
|
||||
|
||||
static_assert(is_same<underlying_type<memory_order>::type, __memory_order_underlying_t>::value,
|
||||
static_assert(is_same<__underlying_type_t<memory_order>, __memory_order_underlying_t>::value,
|
||||
"unexpected underlying type for std::memory_order");
|
||||
|
||||
inline constexpr auto memory_order_relaxed = memory_order::relaxed;
|
||||
|
|
|
|||
3
lib/libcxx/include/__atomic/support.h
vendored
3
lib/libcxx/include/__atomic/support.h
vendored
|
|
@ -10,7 +10,6 @@
|
|||
#define _LIBCPP___ATOMIC_SUPPORT_H
|
||||
|
||||
#include <__config>
|
||||
#include <__type_traits/is_trivially_copyable.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
|
|
@ -113,8 +112,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
|
||||
template <typename _Tp, typename _Base = __cxx_atomic_base_impl<_Tp> >
|
||||
struct __cxx_atomic_impl : public _Base {
|
||||
static_assert(is_trivially_copyable<_Tp>::value, "std::atomic<T> requires that 'T' be a trivially copyable type");
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __cxx_atomic_impl() _NOEXCEPT = default;
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __cxx_atomic_impl(_Tp __value) _NOEXCEPT : _Base(__value) {}
|
||||
};
|
||||
|
|
|
|||
2
lib/libcxx/include/__atomic/support/c11.h
vendored
2
lib/libcxx/include/__atomic/support/c11.h
vendored
|
|
@ -35,7 +35,7 @@ struct __cxx_atomic_base_impl {
|
|||
}
|
||||
#endif // _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_CONSTEXPR explicit __cxx_atomic_base_impl(_Tp __value) _NOEXCEPT : __a_value(__value) {}
|
||||
_LIBCPP_DISABLE_EXTENSION_WARNING _Atomic(_Tp) __a_value;
|
||||
_Atomic(_Tp) __a_value;
|
||||
};
|
||||
|
||||
#define __cxx_atomic_is_lock_free(__s) __c11_atomic_is_lock_free(__s)
|
||||
|
|
|
|||
4
lib/libcxx/include/__bit/bit_ceil.h
vendored
4
lib/libcxx/include/__bit/bit_ceil.h
vendored
|
|
@ -11,8 +11,8 @@
|
|||
|
||||
#include <__assert>
|
||||
#include <__bit/countl.h>
|
||||
#include <__concepts/arithmetic.h>
|
||||
#include <__config>
|
||||
#include <__type_traits/integer_traits.h>
|
||||
#include <limits>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
|
|
@ -41,7 +41,7 @@ template <class _Tp>
|
|||
|
||||
# if _LIBCPP_STD_VER >= 20
|
||||
|
||||
template <__libcpp_unsigned_integer _Tp>
|
||||
template <__unsigned_integer _Tp>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_ceil(_Tp __t) noexcept {
|
||||
return std::__bit_ceil(__t);
|
||||
}
|
||||
|
|
|
|||
5
lib/libcxx/include/__bit/bit_floor.h
vendored
5
lib/libcxx/include/__bit/bit_floor.h
vendored
|
|
@ -10,9 +10,8 @@
|
|||
#define _LIBCPP___BIT_BIT_FLOOR_H
|
||||
|
||||
#include <__bit/bit_log2.h>
|
||||
#include <__concepts/arithmetic.h>
|
||||
#include <__config>
|
||||
#include <limits>
|
||||
#include <__type_traits/integer_traits.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
|
|
@ -22,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
|
||||
template <__libcpp_unsigned_integer _Tp>
|
||||
template <__unsigned_integer _Tp>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp bit_floor(_Tp __t) noexcept {
|
||||
return __t == 0 ? 0 : _Tp{1} << std::__bit_log2(__t);
|
||||
}
|
||||
|
|
|
|||
10
lib/libcxx/include/__bit/bit_log2.h
vendored
10
lib/libcxx/include/__bit/bit_log2.h
vendored
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#include <__bit/countl.h>
|
||||
#include <__config>
|
||||
#include <__type_traits/is_unsigned_integer.h>
|
||||
#include <__type_traits/integer_traits.h>
|
||||
#include <limits>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
|
|
@ -20,16 +20,12 @@
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER >= 14
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_log2(_Tp __t) noexcept {
|
||||
static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__bit_log2 requires an unsigned integer type");
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __bit_log2(_Tp __t) _NOEXCEPT {
|
||||
static_assert(__is_unsigned_integer_v<_Tp>, "__bit_log2 requires an unsigned integer type");
|
||||
return numeric_limits<_Tp>::digits - 1 - std::__countl_zero(__t);
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 14
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___BIT_BIT_LOG2_H
|
||||
|
|
|
|||
4
lib/libcxx/include/__bit/bit_width.h
vendored
4
lib/libcxx/include/__bit/bit_width.h
vendored
|
|
@ -10,8 +10,8 @@
|
|||
#define _LIBCPP___BIT_BIT_WIDTH_H
|
||||
|
||||
#include <__bit/bit_log2.h>
|
||||
#include <__concepts/arithmetic.h>
|
||||
#include <__config>
|
||||
#include <__type_traits/integer_traits.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <__libcpp_unsigned_integer _Tp>
|
||||
template <__unsigned_integer _Tp>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int bit_width(_Tp __t) noexcept {
|
||||
return __t == 0 ? 0 : std::__bit_log2(__t) + 1;
|
||||
}
|
||||
|
|
|
|||
72
lib/libcxx/include/__bit/countl.h
vendored
72
lib/libcxx/include/__bit/countl.h
vendored
|
|
@ -6,16 +6,11 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// TODO: __builtin_clzg is available since Clang 19 and GCC 14. When support for older versions is dropped, we can
|
||||
// refactor this code to exclusively use __builtin_clzg.
|
||||
|
||||
#ifndef _LIBCPP___BIT_COUNTL_H
|
||||
#define _LIBCPP___BIT_COUNTL_H
|
||||
|
||||
#include <__bit/rotate.h>
|
||||
#include <__concepts/arithmetic.h>
|
||||
#include <__config>
|
||||
#include <__type_traits/is_unsigned_integer.h>
|
||||
#include <__type_traits/integer_traits.h>
|
||||
#include <limits>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
|
|
@ -27,79 +22,20 @@ _LIBCPP_PUSH_MACROS
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned __x) _NOEXCEPT {
|
||||
return __builtin_clz(__x);
|
||||
}
|
||||
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned long __x) _NOEXCEPT {
|
||||
return __builtin_clzl(__x);
|
||||
}
|
||||
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(unsigned long long __x) _NOEXCEPT {
|
||||
return __builtin_clzll(__x);
|
||||
}
|
||||
|
||||
#if _LIBCPP_HAS_INT128
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_clz(__uint128_t __x) _NOEXCEPT {
|
||||
# if __has_builtin(__builtin_clzg)
|
||||
return __builtin_clzg(__x);
|
||||
# else
|
||||
// The function is written in this form due to C++ constexpr limitations.
|
||||
// The algorithm:
|
||||
// - Test whether any bit in the high 64-bits is set
|
||||
// - No bits set:
|
||||
// - The high 64-bits contain 64 leading zeros,
|
||||
// - Add the result of the low 64-bits.
|
||||
// - Any bits set:
|
||||
// - The number of leading zeros of the input is the number of leading
|
||||
// zeros in the high 64-bits.
|
||||
return ((__x >> 64) == 0) ? (64 + __builtin_clzll(static_cast<unsigned long long>(__x)))
|
||||
: __builtin_clzll(static_cast<unsigned long long>(__x >> 64));
|
||||
# endif
|
||||
}
|
||||
#endif // _LIBCPP_HAS_INT128
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __countl_zero(_Tp __t) _NOEXCEPT {
|
||||
static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__countl_zero requires an unsigned integer type");
|
||||
#if __has_builtin(__builtin_clzg)
|
||||
static_assert(__is_unsigned_integer_v<_Tp>, "__countl_zero requires an unsigned integer type");
|
||||
return __builtin_clzg(__t, numeric_limits<_Tp>::digits);
|
||||
#else // __has_builtin(__builtin_clzg)
|
||||
if (__t == 0)
|
||||
return numeric_limits<_Tp>::digits;
|
||||
|
||||
if (sizeof(_Tp) <= sizeof(unsigned int))
|
||||
return std::__libcpp_clz(static_cast<unsigned int>(__t)) -
|
||||
(numeric_limits<unsigned int>::digits - numeric_limits<_Tp>::digits);
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long))
|
||||
return std::__libcpp_clz(static_cast<unsigned long>(__t)) -
|
||||
(numeric_limits<unsigned long>::digits - numeric_limits<_Tp>::digits);
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long long))
|
||||
return std::__libcpp_clz(static_cast<unsigned long long>(__t)) -
|
||||
(numeric_limits<unsigned long long>::digits - numeric_limits<_Tp>::digits);
|
||||
else {
|
||||
int __ret = 0;
|
||||
int __iter = 0;
|
||||
const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
|
||||
while (true) {
|
||||
__t = std::__rotl(__t, __ulldigits);
|
||||
if ((__iter = std::__countl_zero(static_cast<unsigned long long>(__t))) != __ulldigits)
|
||||
break;
|
||||
__ret += __iter;
|
||||
}
|
||||
return __ret + __iter;
|
||||
}
|
||||
#endif // __has_builtin(__builtin_clzg)
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
|
||||
template <__libcpp_unsigned_integer _Tp>
|
||||
template <__unsigned_integer _Tp>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countl_zero(_Tp __t) noexcept {
|
||||
return std::__countl_zero(__t);
|
||||
}
|
||||
|
||||
template <__libcpp_unsigned_integer _Tp>
|
||||
template <__unsigned_integer _Tp>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countl_one(_Tp __t) noexcept {
|
||||
return __t != numeric_limits<_Tp>::max() ? std::countl_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits;
|
||||
}
|
||||
|
|
|
|||
45
lib/libcxx/include/__bit/countr.h
vendored
45
lib/libcxx/include/__bit/countr.h
vendored
|
|
@ -6,15 +6,11 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// TODO: __builtin_ctzg is available since Clang 19 and GCC 14. When support for older versions is dropped, we can
|
||||
// refactor this code to exclusively use __builtin_ctzg.
|
||||
|
||||
#ifndef _LIBCPP___BIT_COUNTR_H
|
||||
#define _LIBCPP___BIT_COUNTR_H
|
||||
|
||||
#include <__bit/rotate.h>
|
||||
#include <__concepts/arithmetic.h>
|
||||
#include <__config>
|
||||
#include <__type_traits/integer_traits.h>
|
||||
#include <limits>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
|
|
@ -26,51 +22,20 @@ _LIBCPP_PUSH_MACROS
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ctz(unsigned __x) _NOEXCEPT {
|
||||
return __builtin_ctz(__x);
|
||||
}
|
||||
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ctz(unsigned long __x) _NOEXCEPT {
|
||||
return __builtin_ctzl(__x);
|
||||
}
|
||||
|
||||
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_ctz(unsigned long long __x) _NOEXCEPT {
|
||||
return __builtin_ctzll(__x);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int __countr_zero(_Tp __t) _NOEXCEPT {
|
||||
#if __has_builtin(__builtin_ctzg)
|
||||
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __countr_zero(_Tp __t) _NOEXCEPT {
|
||||
static_assert(__is_unsigned_integer_v<_Tp>, "__countr_zero only works with unsigned types");
|
||||
return __builtin_ctzg(__t, numeric_limits<_Tp>::digits);
|
||||
#else // __has_builtin(__builtin_ctzg)
|
||||
if (__t == 0)
|
||||
return numeric_limits<_Tp>::digits;
|
||||
if (sizeof(_Tp) <= sizeof(unsigned int))
|
||||
return std::__libcpp_ctz(static_cast<unsigned int>(__t));
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long))
|
||||
return std::__libcpp_ctz(static_cast<unsigned long>(__t));
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long long))
|
||||
return std::__libcpp_ctz(static_cast<unsigned long long>(__t));
|
||||
else {
|
||||
int __ret = 0;
|
||||
const unsigned int __ulldigits = numeric_limits<unsigned long long>::digits;
|
||||
while (static_cast<unsigned long long>(__t) == 0uLL) {
|
||||
__ret += __ulldigits;
|
||||
__t >>= __ulldigits;
|
||||
}
|
||||
return __ret + std::__libcpp_ctz(static_cast<unsigned long long>(__t));
|
||||
}
|
||||
#endif // __has_builtin(__builtin_ctzg)
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
|
||||
template <__libcpp_unsigned_integer _Tp>
|
||||
template <__unsigned_integer _Tp>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countr_zero(_Tp __t) noexcept {
|
||||
return std::__countr_zero(__t);
|
||||
}
|
||||
|
||||
template <__libcpp_unsigned_integer _Tp>
|
||||
template <__unsigned_integer _Tp>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int countr_one(_Tp __t) noexcept {
|
||||
return __t != numeric_limits<_Tp>::max() ? std::countr_zero(static_cast<_Tp>(~__t)) : numeric_limits<_Tp>::digits;
|
||||
}
|
||||
|
|
|
|||
4
lib/libcxx/include/__bit/has_single_bit.h
vendored
4
lib/libcxx/include/__bit/has_single_bit.h
vendored
|
|
@ -9,8 +9,8 @@
|
|||
#ifndef _LIBCPP___BIT_HAS_SINGLE_BIT_H
|
||||
#define _LIBCPP___BIT_HAS_SINGLE_BIT_H
|
||||
|
||||
#include <__concepts/arithmetic.h>
|
||||
#include <__config>
|
||||
#include <__type_traits/integer_traits.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
|
|
@ -23,7 +23,7 @@ _LIBCPP_PUSH_MACROS
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <__libcpp_unsigned_integer _Tp>
|
||||
template <__unsigned_integer _Tp>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool has_single_bit(_Tp __t) noexcept {
|
||||
return __t != 0 && (((__t & (__t - 1)) == 0));
|
||||
}
|
||||
|
|
|
|||
44
lib/libcxx/include/__bit/popcount.h
vendored
44
lib/libcxx/include/__bit/popcount.h
vendored
|
|
@ -6,16 +6,11 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// TODO: __builtin_popcountg is available since Clang 19 and GCC 14. When support for older versions is dropped, we can
|
||||
// refactor this code to exclusively use __builtin_popcountg.
|
||||
|
||||
#ifndef _LIBCPP___BIT_POPCOUNT_H
|
||||
#define _LIBCPP___BIT_POPCOUNT_H
|
||||
|
||||
#include <__bit/rotate.h>
|
||||
#include <__concepts/arithmetic.h>
|
||||
#include <__config>
|
||||
#include <limits>
|
||||
#include <__type_traits/integer_traits.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
|
|
@ -26,43 +21,20 @@ _LIBCPP_PUSH_MACROS
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount(unsigned __x) _NOEXCEPT {
|
||||
return __builtin_popcount(__x);
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount(unsigned long __x) _NOEXCEPT {
|
||||
return __builtin_popcountl(__x);
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __libcpp_popcount(unsigned long long __x) _NOEXCEPT {
|
||||
return __builtin_popcountll(__x);
|
||||
template <class _Tp>
|
||||
[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR int __popcount(_Tp __t) _NOEXCEPT {
|
||||
static_assert(__is_unsigned_integer_v<_Tp>, "__popcount only works with unsigned types");
|
||||
return __builtin_popcountg(__t);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
|
||||
template <__libcpp_unsigned_integer _Tp>
|
||||
template <__unsigned_integer _Tp>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr int popcount(_Tp __t) noexcept {
|
||||
# if __has_builtin(__builtin_popcountg)
|
||||
return __builtin_popcountg(__t);
|
||||
# else // __has_builtin(__builtin_popcountg)
|
||||
if (sizeof(_Tp) <= sizeof(unsigned int))
|
||||
return std::__libcpp_popcount(static_cast<unsigned int>(__t));
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long))
|
||||
return std::__libcpp_popcount(static_cast<unsigned long>(__t));
|
||||
else if (sizeof(_Tp) <= sizeof(unsigned long long))
|
||||
return std::__libcpp_popcount(static_cast<unsigned long long>(__t));
|
||||
else {
|
||||
int __ret = 0;
|
||||
while (__t != 0) {
|
||||
__ret += std::__libcpp_popcount(static_cast<unsigned long long>(__t));
|
||||
__t >>= numeric_limits<unsigned long long>::digits;
|
||||
}
|
||||
return __ret;
|
||||
}
|
||||
# endif // __has_builtin(__builtin_popcountg)
|
||||
return std::__popcount(__t);
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
#endif
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
|
|
|
|||
11
lib/libcxx/include/__bit/rotate.h
vendored
11
lib/libcxx/include/__bit/rotate.h
vendored
|
|
@ -9,9 +9,8 @@
|
|||
#ifndef _LIBCPP___BIT_ROTATE_H
|
||||
#define _LIBCPP___BIT_ROTATE_H
|
||||
|
||||
#include <__concepts/arithmetic.h>
|
||||
#include <__config>
|
||||
#include <__type_traits/is_unsigned_integer.h>
|
||||
#include <__type_traits/integer_traits.h>
|
||||
#include <limits>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
|
|
@ -25,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
// the rotr function becomes the ROR instruction.
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __rotl(_Tp __x, int __s) _NOEXCEPT {
|
||||
static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__rotl requires an unsigned integer type");
|
||||
static_assert(__is_unsigned_integer_v<_Tp>, "__rotl requires an unsigned integer type");
|
||||
const int __n = numeric_limits<_Tp>::digits;
|
||||
int __r = __s % __n;
|
||||
|
||||
|
|
@ -40,7 +39,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __rotl(_Tp __x, int __s)
|
|||
|
||||
template <class _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __rotr(_Tp __x, int __s) _NOEXCEPT {
|
||||
static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__rotr requires an unsigned integer type");
|
||||
static_assert(__is_unsigned_integer_v<_Tp>, "__rotr requires an unsigned integer type");
|
||||
const int __n = numeric_limits<_Tp>::digits;
|
||||
int __r = __s % __n;
|
||||
|
||||
|
|
@ -55,12 +54,12 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __rotr(_Tp __x, int __s)
|
|||
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
|
||||
template <__libcpp_unsigned_integer _Tp>
|
||||
template <__unsigned_integer _Tp>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotl(_Tp __t, int __cnt) noexcept {
|
||||
return std::__rotl(__t, __cnt);
|
||||
}
|
||||
|
||||
template <__libcpp_unsigned_integer _Tp>
|
||||
template <__unsigned_integer _Tp>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp rotr(_Tp __t, int __cnt) noexcept {
|
||||
return std::__rotr(__t, __cnt);
|
||||
}
|
||||
|
|
|
|||
708
lib/libcxx/include/__bit_reference
vendored
708
lib/libcxx/include/__bit_reference
vendored
|
|
@ -10,21 +10,35 @@
|
|||
#ifndef _LIBCPP___BIT_REFERENCE
|
||||
#define _LIBCPP___BIT_REFERENCE
|
||||
|
||||
#include <__algorithm/comp.h>
|
||||
#include <__algorithm/copy.h>
|
||||
#include <__algorithm/copy_backward.h>
|
||||
#include <__algorithm/copy_n.h>
|
||||
#include <__algorithm/equal.h>
|
||||
#include <__algorithm/min.h>
|
||||
#include <__algorithm/rotate.h>
|
||||
#include <__algorithm/swap_ranges.h>
|
||||
#include <__assert>
|
||||
#include <__bit/countr.h>
|
||||
#include <__compare/ordering.h>
|
||||
#include <__config>
|
||||
#include <__cstddef/ptrdiff_t.h>
|
||||
#include <__cstddef/size_t.h>
|
||||
#include <__functional/identity.h>
|
||||
#include <__fwd/bit_reference.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__memory/construct_at.h>
|
||||
#include <__memory/pointer_traits.h>
|
||||
#include <__type_traits/conditional.h>
|
||||
#include <__type_traits/desugars_to.h>
|
||||
#include <__type_traits/enable_if.h>
|
||||
#include <__type_traits/is_constant_evaluated.h>
|
||||
#include <__type_traits/is_same.h>
|
||||
#include <__type_traits/is_unsigned.h>
|
||||
#include <__type_traits/void_t.h>
|
||||
#include <__utility/pair.h>
|
||||
#include <__utility/swap.h>
|
||||
#include <climits>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
|
|
@ -55,6 +69,53 @@ struct __size_difference_type_traits<_Cp, __void_t<typename _Cp::difference_type
|
|||
using size_type = typename _Cp::size_type;
|
||||
};
|
||||
|
||||
// The `__x_mask` functions are designed to work exclusively with any unsigned `_StorageType`s, including small
|
||||
// integral types such as unsigned char/short, `uint8_t`, and `uint16_t`. To prevent undefined behavior or
|
||||
// ambiguities due to integral promotions for the small integral types, all intermediate bitwise operations are
|
||||
// explicitly cast back to the unsigned `_StorageType`.
|
||||
|
||||
// Creates a mask of type `_StorageType` with a specified number of leading zeros (__clz) and sets all remaining
|
||||
// bits to one.
|
||||
template <class _StorageType>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __trailing_mask(unsigned __clz) {
|
||||
static_assert(is_unsigned<_StorageType>::value, "__trailing_mask only works with unsigned types");
|
||||
return static_cast<_StorageType>(~static_cast<_StorageType>(0)) >> __clz;
|
||||
}
|
||||
|
||||
// Creates a mask of type `_StorageType` with a specified number of trailing zeros (__ctz) and sets all remaining
|
||||
// bits to one.
|
||||
template <class _StorageType>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __leading_mask(unsigned __ctz) {
|
||||
static_assert(is_unsigned<_StorageType>::value, "__leading_mask only works with unsigned types");
|
||||
return static_cast<_StorageType>(~static_cast<_StorageType>(0)) << __ctz;
|
||||
}
|
||||
|
||||
// Creates a mask of type `_StorageType` with a specified number of leading zeros (__clz), a specified number of
|
||||
// trailing zeros (__ctz), and sets all bits in between to one.
|
||||
template <class _StorageType>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _StorageType __middle_mask(unsigned __clz, unsigned __ctz) {
|
||||
static_assert(is_unsigned<_StorageType>::value, "__middle_mask only works with unsigned types");
|
||||
return std::__leading_mask<_StorageType>(__ctz) & std::__trailing_mask<_StorageType>(__clz);
|
||||
}
|
||||
|
||||
// This function is designed to operate correctly even for smaller integral types like `uint8_t`, `uint16_t`,
|
||||
// or `unsigned short`.
|
||||
// See https://github.com/llvm/llvm-project/pull/122410.
|
||||
template <class _StoragePointer>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
|
||||
__fill_masked_range(_StoragePointer __word, unsigned __clz, unsigned __ctz, bool __fill_val) {
|
||||
static_assert(is_unsigned<typename pointer_traits<_StoragePointer>::element_type>::value,
|
||||
"__fill_masked_range must be called with unsigned type");
|
||||
using _StorageType = typename pointer_traits<_StoragePointer>::element_type;
|
||||
_LIBCPP_ASSERT_VALID_INPUT_RANGE(
|
||||
__ctz + __clz < sizeof(_StorageType) * CHAR_BIT, "__fill_masked_range called with invalid range");
|
||||
_StorageType __m = std::__middle_mask<_StorageType>(__clz, __ctz);
|
||||
if (__fill_val)
|
||||
*__word |= __m;
|
||||
else
|
||||
*__word &= ~__m;
|
||||
}
|
||||
|
||||
template <class _Cp, bool = __has_storage_type<_Cp>::value>
|
||||
class __bit_reference {
|
||||
using __storage_type _LIBCPP_NODEBUG = typename _Cp::__storage_type;
|
||||
|
|
@ -104,7 +165,7 @@ public:
|
|||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void flip() _NOEXCEPT { *__seg_ ^= __mask_; }
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false> operator&() const _NOEXCEPT {
|
||||
return __bit_iterator<_Cp, false>(__seg_, static_cast<unsigned>(std::__libcpp_ctz(__mask_)));
|
||||
return __bit_iterator<_Cp, false>(__seg_, static_cast<unsigned>(std::__countr_zero(__mask_)));
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -173,7 +234,7 @@ public:
|
|||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, true> operator&() const _NOEXCEPT {
|
||||
return __bit_iterator<_Cp, true>(__seg_, static_cast<unsigned>(std::__libcpp_ctz(__mask_)));
|
||||
return __bit_iterator<_Cp, true>(__seg_, static_cast<unsigned>(std::__countr_zero(__mask_)));
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -183,422 +244,6 @@ private:
|
|||
__mask_(__m) {}
|
||||
};
|
||||
|
||||
// copy
|
||||
|
||||
template <class _Cp, bool _IsConst>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_aligned(
|
||||
__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
|
||||
using _In = __bit_iterator<_Cp, _IsConst>;
|
||||
using difference_type = typename _In::difference_type;
|
||||
using __storage_type = typename _In::__storage_type;
|
||||
|
||||
const int __bits_per_word = _In::__bits_per_word;
|
||||
difference_type __n = __last - __first;
|
||||
if (__n > 0) {
|
||||
// do first word
|
||||
if (__first.__ctz_ != 0) {
|
||||
unsigned __clz = __bits_per_word - __first.__ctz_;
|
||||
difference_type __dn = std::min(static_cast<difference_type>(__clz), __n);
|
||||
__n -= __dn;
|
||||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn));
|
||||
__storage_type __b = *__first.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b;
|
||||
__result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
|
||||
__result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
|
||||
++__first.__seg_;
|
||||
// __first.__ctz_ = 0;
|
||||
}
|
||||
// __first.__ctz_ == 0;
|
||||
// do middle words
|
||||
__storage_type __nw = __n / __bits_per_word;
|
||||
std::copy_n(std::__to_address(__first.__seg_), __nw, std::__to_address(__result.__seg_));
|
||||
__n -= __nw * __bits_per_word;
|
||||
__result.__seg_ += __nw;
|
||||
// do last word
|
||||
if (__n > 0) {
|
||||
__first.__seg_ += __nw;
|
||||
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__storage_type __b = *__first.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b;
|
||||
__result.__ctz_ = static_cast<unsigned>(__n);
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _Cp, bool _IsConst>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_unaligned(
|
||||
__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
|
||||
using _In = __bit_iterator<_Cp, _IsConst>;
|
||||
using difference_type = typename _In::difference_type;
|
||||
using __storage_type = typename _In::__storage_type;
|
||||
|
||||
const int __bits_per_word = _In::__bits_per_word;
|
||||
difference_type __n = __last - __first;
|
||||
if (__n > 0) {
|
||||
// do first word
|
||||
if (__first.__ctz_ != 0) {
|
||||
unsigned __clz_f = __bits_per_word - __first.__ctz_;
|
||||
difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n);
|
||||
__n -= __dn;
|
||||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
|
||||
__storage_type __b = *__first.__seg_ & __m;
|
||||
unsigned __clz_r = __bits_per_word - __result.__ctz_;
|
||||
__storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
|
||||
__m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn));
|
||||
*__result.__seg_ &= ~__m;
|
||||
if (__result.__ctz_ > __first.__ctz_)
|
||||
*__result.__seg_ |= __b << (__result.__ctz_ - __first.__ctz_);
|
||||
else
|
||||
*__result.__seg_ |= __b >> (__first.__ctz_ - __result.__ctz_);
|
||||
__result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word;
|
||||
__result.__ctz_ = static_cast<unsigned>((__ddn + __result.__ctz_) % __bits_per_word);
|
||||
__dn -= __ddn;
|
||||
if (__dn > 0) {
|
||||
__m = ~__storage_type(0) >> (__bits_per_word - __dn);
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b >> (__first.__ctz_ + __ddn);
|
||||
__result.__ctz_ = static_cast<unsigned>(__dn);
|
||||
}
|
||||
++__first.__seg_;
|
||||
// __first.__ctz_ = 0;
|
||||
}
|
||||
// __first.__ctz_ == 0;
|
||||
// do middle words
|
||||
unsigned __clz_r = __bits_per_word - __result.__ctz_;
|
||||
__storage_type __m = ~__storage_type(0) << __result.__ctz_;
|
||||
for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) {
|
||||
__storage_type __b = *__first.__seg_;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b << __result.__ctz_;
|
||||
++__result.__seg_;
|
||||
*__result.__seg_ &= __m;
|
||||
*__result.__seg_ |= __b >> __clz_r;
|
||||
}
|
||||
// do last word
|
||||
if (__n > 0) {
|
||||
__m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__storage_type __b = *__first.__seg_ & __m;
|
||||
__storage_type __dn = std::min(__n, static_cast<difference_type>(__clz_r));
|
||||
__m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn));
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b << __result.__ctz_;
|
||||
__result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
|
||||
__result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
|
||||
__n -= __dn;
|
||||
if (__n > 0) {
|
||||
__m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b >> __dn;
|
||||
__result.__ctz_ = static_cast<unsigned>(__n);
|
||||
}
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _Cp, bool _IsConst>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false>
|
||||
copy(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
|
||||
if (__first.__ctz_ == __result.__ctz_)
|
||||
return std::__copy_aligned(__first, __last, __result);
|
||||
return std::__copy_unaligned(__first, __last, __result);
|
||||
}
|
||||
|
||||
// copy_backward
|
||||
|
||||
template <class _Cp, bool _IsConst>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_backward_aligned(
|
||||
__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
|
||||
using _In = __bit_iterator<_Cp, _IsConst>;
|
||||
using difference_type = typename _In::difference_type;
|
||||
using __storage_type = typename _In::__storage_type;
|
||||
|
||||
const int __bits_per_word = _In::__bits_per_word;
|
||||
difference_type __n = __last - __first;
|
||||
if (__n > 0) {
|
||||
// do first word
|
||||
if (__last.__ctz_ != 0) {
|
||||
difference_type __dn = std::min(static_cast<difference_type>(__last.__ctz_), __n);
|
||||
__n -= __dn;
|
||||
unsigned __clz = __bits_per_word - __last.__ctz_;
|
||||
__storage_type __m = (~__storage_type(0) << (__last.__ctz_ - __dn)) & (~__storage_type(0) >> __clz);
|
||||
__storage_type __b = *__last.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b;
|
||||
__result.__ctz_ = static_cast<unsigned>(((-__dn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word);
|
||||
// __last.__ctz_ = 0
|
||||
}
|
||||
// __last.__ctz_ == 0 || __n == 0
|
||||
// __result.__ctz_ == 0 || __n == 0
|
||||
// do middle words
|
||||
__storage_type __nw = __n / __bits_per_word;
|
||||
__result.__seg_ -= __nw;
|
||||
__last.__seg_ -= __nw;
|
||||
std::copy_n(std::__to_address(__last.__seg_), __nw, std::__to_address(__result.__seg_));
|
||||
__n -= __nw * __bits_per_word;
|
||||
// do last word
|
||||
if (__n > 0) {
|
||||
__storage_type __m = ~__storage_type(0) << (__bits_per_word - __n);
|
||||
__storage_type __b = *--__last.__seg_ & __m;
|
||||
*--__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b;
|
||||
__result.__ctz_ = static_cast<unsigned>(-__n & (__bits_per_word - 1));
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _Cp, bool _IsConst>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> __copy_backward_unaligned(
|
||||
__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
|
||||
using _In = __bit_iterator<_Cp, _IsConst>;
|
||||
using difference_type = typename _In::difference_type;
|
||||
using __storage_type = typename _In::__storage_type;
|
||||
|
||||
const int __bits_per_word = _In::__bits_per_word;
|
||||
difference_type __n = __last - __first;
|
||||
if (__n > 0) {
|
||||
// do first word
|
||||
if (__last.__ctz_ != 0) {
|
||||
difference_type __dn = std::min(static_cast<difference_type>(__last.__ctz_), __n);
|
||||
__n -= __dn;
|
||||
unsigned __clz_l = __bits_per_word - __last.__ctz_;
|
||||
__storage_type __m = (~__storage_type(0) << (__last.__ctz_ - __dn)) & (~__storage_type(0) >> __clz_l);
|
||||
__storage_type __b = *__last.__seg_ & __m;
|
||||
unsigned __clz_r = __bits_per_word - __result.__ctz_;
|
||||
__storage_type __ddn = std::min(__dn, static_cast<difference_type>(__result.__ctz_));
|
||||
if (__ddn > 0) {
|
||||
__m = (~__storage_type(0) << (__result.__ctz_ - __ddn)) & (~__storage_type(0) >> __clz_r);
|
||||
*__result.__seg_ &= ~__m;
|
||||
if (__result.__ctz_ > __last.__ctz_)
|
||||
*__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_);
|
||||
else
|
||||
*__result.__seg_ |= __b >> (__last.__ctz_ - __result.__ctz_);
|
||||
__result.__ctz_ = static_cast<unsigned>(((-__ddn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word);
|
||||
__dn -= __ddn;
|
||||
}
|
||||
if (__dn > 0) {
|
||||
// __result.__ctz_ == 0
|
||||
--__result.__seg_;
|
||||
__result.__ctz_ = static_cast<unsigned>(-__dn & (__bits_per_word - 1));
|
||||
__m = ~__storage_type(0) << __result.__ctz_;
|
||||
*__result.__seg_ &= ~__m;
|
||||
__last.__ctz_ -= __dn + __ddn;
|
||||
*__result.__seg_ |= __b << (__result.__ctz_ - __last.__ctz_);
|
||||
}
|
||||
// __last.__ctz_ = 0
|
||||
}
|
||||
// __last.__ctz_ == 0 || __n == 0
|
||||
// __result.__ctz_ != 0 || __n == 0
|
||||
// do middle words
|
||||
unsigned __clz_r = __bits_per_word - __result.__ctz_;
|
||||
__storage_type __m = ~__storage_type(0) >> __clz_r;
|
||||
for (; __n >= __bits_per_word; __n -= __bits_per_word) {
|
||||
__storage_type __b = *--__last.__seg_;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b >> __clz_r;
|
||||
*--__result.__seg_ &= __m;
|
||||
*__result.__seg_ |= __b << __result.__ctz_;
|
||||
}
|
||||
// do last word
|
||||
if (__n > 0) {
|
||||
__m = ~__storage_type(0) << (__bits_per_word - __n);
|
||||
__storage_type __b = *--__last.__seg_ & __m;
|
||||
__clz_r = __bits_per_word - __result.__ctz_;
|
||||
__storage_type __dn = std::min(__n, static_cast<difference_type>(__result.__ctz_));
|
||||
__m = (~__storage_type(0) << (__result.__ctz_ - __dn)) & (~__storage_type(0) >> __clz_r);
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b >> (__bits_per_word - __result.__ctz_);
|
||||
__result.__ctz_ = static_cast<unsigned>(((-__dn & (__bits_per_word - 1)) + __result.__ctz_) % __bits_per_word);
|
||||
__n -= __dn;
|
||||
if (__n > 0) {
|
||||
// __result.__ctz_ == 0
|
||||
--__result.__seg_;
|
||||
__result.__ctz_ = static_cast<unsigned>(-__n & (__bits_per_word - 1));
|
||||
__m = ~__storage_type(0) << __result.__ctz_;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b << (__result.__ctz_ - (__bits_per_word - __n - __dn));
|
||||
}
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _Cp, bool _IsConst>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __bit_iterator<_Cp, false> copy_backward(
|
||||
__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
|
||||
if (__last.__ctz_ == __result.__ctz_)
|
||||
return std::__copy_backward_aligned(__first, __last, __result);
|
||||
return std::__copy_backward_unaligned(__first, __last, __result);
|
||||
}
|
||||
|
||||
// move
|
||||
|
||||
template <class _Cp, bool _IsConst>
|
||||
inline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false>
|
||||
move(__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
|
||||
return std::copy(__first, __last, __result);
|
||||
}
|
||||
|
||||
// move_backward
|
||||
|
||||
template <class _Cp, bool _IsConst>
|
||||
inline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false> move_backward(
|
||||
__bit_iterator<_Cp, _IsConst> __first, __bit_iterator<_Cp, _IsConst> __last, __bit_iterator<_Cp, false> __result) {
|
||||
return std::copy_backward(__first, __last, __result);
|
||||
}
|
||||
|
||||
// swap_ranges
|
||||
|
||||
template <class _Cl, class _Cr>
|
||||
_LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> __swap_ranges_aligned(
|
||||
__bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) {
|
||||
using _I1 = __bit_iterator<_Cl, false>;
|
||||
using difference_type = typename _I1::difference_type;
|
||||
using __storage_type = typename _I1::__storage_type;
|
||||
|
||||
const int __bits_per_word = _I1::__bits_per_word;
|
||||
difference_type __n = __last - __first;
|
||||
if (__n > 0) {
|
||||
// do first word
|
||||
if (__first.__ctz_ != 0) {
|
||||
unsigned __clz = __bits_per_word - __first.__ctz_;
|
||||
difference_type __dn = std::min(static_cast<difference_type>(__clz), __n);
|
||||
__n -= __dn;
|
||||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz - __dn));
|
||||
__storage_type __b1 = *__first.__seg_ & __m;
|
||||
*__first.__seg_ &= ~__m;
|
||||
__storage_type __b2 = *__result.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b1;
|
||||
*__first.__seg_ |= __b2;
|
||||
__result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
|
||||
__result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
|
||||
++__first.__seg_;
|
||||
// __first.__ctz_ = 0;
|
||||
}
|
||||
// __first.__ctz_ == 0;
|
||||
// do middle words
|
||||
for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_, ++__result.__seg_)
|
||||
swap(*__first.__seg_, *__result.__seg_);
|
||||
// do last word
|
||||
if (__n > 0) {
|
||||
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__storage_type __b1 = *__first.__seg_ & __m;
|
||||
*__first.__seg_ &= ~__m;
|
||||
__storage_type __b2 = *__result.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b1;
|
||||
*__first.__seg_ |= __b2;
|
||||
__result.__ctz_ = static_cast<unsigned>(__n);
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _Cl, class _Cr>
|
||||
_LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> __swap_ranges_unaligned(
|
||||
__bit_iterator<_Cl, false> __first, __bit_iterator<_Cl, false> __last, __bit_iterator<_Cr, false> __result) {
|
||||
using _I1 = __bit_iterator<_Cl, false>;
|
||||
using difference_type = typename _I1::difference_type;
|
||||
using __storage_type = typename _I1::__storage_type;
|
||||
|
||||
const int __bits_per_word = _I1::__bits_per_word;
|
||||
difference_type __n = __last - __first;
|
||||
if (__n > 0) {
|
||||
// do first word
|
||||
if (__first.__ctz_ != 0) {
|
||||
unsigned __clz_f = __bits_per_word - __first.__ctz_;
|
||||
difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n);
|
||||
__n -= __dn;
|
||||
__storage_type __m = (~__storage_type(0) << __first.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
|
||||
__storage_type __b1 = *__first.__seg_ & __m;
|
||||
*__first.__seg_ &= ~__m;
|
||||
unsigned __clz_r = __bits_per_word - __result.__ctz_;
|
||||
__storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
|
||||
__m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn));
|
||||
__storage_type __b2 = *__result.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
if (__result.__ctz_ > __first.__ctz_) {
|
||||
unsigned __s = __result.__ctz_ - __first.__ctz_;
|
||||
*__result.__seg_ |= __b1 << __s;
|
||||
*__first.__seg_ |= __b2 >> __s;
|
||||
} else {
|
||||
unsigned __s = __first.__ctz_ - __result.__ctz_;
|
||||
*__result.__seg_ |= __b1 >> __s;
|
||||
*__first.__seg_ |= __b2 << __s;
|
||||
}
|
||||
__result.__seg_ += (__ddn + __result.__ctz_) / __bits_per_word;
|
||||
__result.__ctz_ = static_cast<unsigned>((__ddn + __result.__ctz_) % __bits_per_word);
|
||||
__dn -= __ddn;
|
||||
if (__dn > 0) {
|
||||
__m = ~__storage_type(0) >> (__bits_per_word - __dn);
|
||||
__b2 = *__result.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
unsigned __s = __first.__ctz_ + __ddn;
|
||||
*__result.__seg_ |= __b1 >> __s;
|
||||
*__first.__seg_ |= __b2 << __s;
|
||||
__result.__ctz_ = static_cast<unsigned>(__dn);
|
||||
}
|
||||
++__first.__seg_;
|
||||
// __first.__ctz_ = 0;
|
||||
}
|
||||
// __first.__ctz_ == 0;
|
||||
// do middle words
|
||||
__storage_type __m = ~__storage_type(0) << __result.__ctz_;
|
||||
unsigned __clz_r = __bits_per_word - __result.__ctz_;
|
||||
for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first.__seg_) {
|
||||
__storage_type __b1 = *__first.__seg_;
|
||||
__storage_type __b2 = *__result.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b1 << __result.__ctz_;
|
||||
*__first.__seg_ = __b2 >> __result.__ctz_;
|
||||
++__result.__seg_;
|
||||
__b2 = *__result.__seg_ & ~__m;
|
||||
*__result.__seg_ &= __m;
|
||||
*__result.__seg_ |= __b1 >> __clz_r;
|
||||
*__first.__seg_ |= __b2 << __clz_r;
|
||||
}
|
||||
// do last word
|
||||
if (__n > 0) {
|
||||
__m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__storage_type __b1 = *__first.__seg_ & __m;
|
||||
*__first.__seg_ &= ~__m;
|
||||
__storage_type __dn = std::min<__storage_type>(__n, __clz_r);
|
||||
__m = (~__storage_type(0) << __result.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn));
|
||||
__storage_type __b2 = *__result.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b1 << __result.__ctz_;
|
||||
*__first.__seg_ |= __b2 >> __result.__ctz_;
|
||||
__result.__seg_ += (__dn + __result.__ctz_) / __bits_per_word;
|
||||
__result.__ctz_ = static_cast<unsigned>((__dn + __result.__ctz_) % __bits_per_word);
|
||||
__n -= __dn;
|
||||
if (__n > 0) {
|
||||
__m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__b2 = *__result.__seg_ & __m;
|
||||
*__result.__seg_ &= ~__m;
|
||||
*__result.__seg_ |= __b1 >> __dn;
|
||||
*__first.__seg_ |= __b2 << __dn;
|
||||
__result.__ctz_ = static_cast<unsigned>(__n);
|
||||
}
|
||||
}
|
||||
}
|
||||
return __result;
|
||||
}
|
||||
|
||||
template <class _Cl, class _Cr>
|
||||
inline _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cr, false> swap_ranges(
|
||||
__bit_iterator<_Cl, false> __first1, __bit_iterator<_Cl, false> __last1, __bit_iterator<_Cr, false> __first2) {
|
||||
if (__first1.__ctz_ == __first2.__ctz_)
|
||||
return std::__swap_ranges_aligned(__first1, __last1, __first2);
|
||||
return std::__swap_ranges_unaligned(__first1, __last1, __first2);
|
||||
}
|
||||
|
||||
// rotate
|
||||
|
||||
template <class _Cp>
|
||||
struct __bit_array {
|
||||
using difference_type _LIBCPP_NODEBUG = typename __size_difference_type_traits<_Cp>::difference_type;
|
||||
|
|
@ -630,166 +275,6 @@ struct __bit_array {
|
|||
}
|
||||
};
|
||||
|
||||
template <class _Cp>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI __bit_iterator<_Cp, false>
|
||||
rotate(__bit_iterator<_Cp, false> __first, __bit_iterator<_Cp, false> __middle, __bit_iterator<_Cp, false> __last) {
|
||||
using _I1 = __bit_iterator<_Cp, false>;
|
||||
using difference_type = typename _I1::difference_type;
|
||||
|
||||
difference_type __d1 = __middle - __first;
|
||||
difference_type __d2 = __last - __middle;
|
||||
_I1 __r = __first + __d2;
|
||||
while (__d1 != 0 && __d2 != 0) {
|
||||
if (__d1 <= __d2) {
|
||||
if (__d1 <= __bit_array<_Cp>::capacity()) {
|
||||
__bit_array<_Cp> __b(__d1);
|
||||
std::copy(__first, __middle, __b.begin());
|
||||
std::copy(__b.begin(), __b.end(), std::copy(__middle, __last, __first));
|
||||
break;
|
||||
} else {
|
||||
__bit_iterator<_Cp, false> __mp = std::swap_ranges(__first, __middle, __middle);
|
||||
__first = __middle;
|
||||
__middle = __mp;
|
||||
__d2 -= __d1;
|
||||
}
|
||||
} else {
|
||||
if (__d2 <= __bit_array<_Cp>::capacity()) {
|
||||
__bit_array<_Cp> __b(__d2);
|
||||
std::copy(__middle, __last, __b.begin());
|
||||
std::copy_backward(__b.begin(), __b.end(), std::copy_backward(__first, __middle, __last));
|
||||
break;
|
||||
} else {
|
||||
__bit_iterator<_Cp, false> __mp = __first + __d2;
|
||||
std::swap_ranges(__first, __mp, __middle);
|
||||
__first = __mp;
|
||||
__d1 -= __d2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return __r;
|
||||
}
|
||||
|
||||
// equal
|
||||
|
||||
template <class _Cp, bool _IC1, bool _IC2>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __equal_unaligned(
|
||||
__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) {
|
||||
using _It = __bit_iterator<_Cp, _IC1>;
|
||||
using difference_type = typename _It::difference_type;
|
||||
using __storage_type = typename _It::__storage_type;
|
||||
|
||||
const int __bits_per_word = _It::__bits_per_word;
|
||||
difference_type __n = __last1 - __first1;
|
||||
if (__n > 0) {
|
||||
// do first word
|
||||
if (__first1.__ctz_ != 0) {
|
||||
unsigned __clz_f = __bits_per_word - __first1.__ctz_;
|
||||
difference_type __dn = std::min(static_cast<difference_type>(__clz_f), __n);
|
||||
__n -= __dn;
|
||||
__storage_type __m = (~__storage_type(0) << __first1.__ctz_) & (~__storage_type(0) >> (__clz_f - __dn));
|
||||
__storage_type __b = *__first1.__seg_ & __m;
|
||||
unsigned __clz_r = __bits_per_word - __first2.__ctz_;
|
||||
__storage_type __ddn = std::min<__storage_type>(__dn, __clz_r);
|
||||
__m = (~__storage_type(0) << __first2.__ctz_) & (~__storage_type(0) >> (__clz_r - __ddn));
|
||||
if (__first2.__ctz_ > __first1.__ctz_) {
|
||||
if ((*__first2.__seg_ & __m) != (__b << (__first2.__ctz_ - __first1.__ctz_)))
|
||||
return false;
|
||||
} else {
|
||||
if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ - __first2.__ctz_)))
|
||||
return false;
|
||||
}
|
||||
__first2.__seg_ += (__ddn + __first2.__ctz_) / __bits_per_word;
|
||||
__first2.__ctz_ = static_cast<unsigned>((__ddn + __first2.__ctz_) % __bits_per_word);
|
||||
__dn -= __ddn;
|
||||
if (__dn > 0) {
|
||||
__m = ~__storage_type(0) >> (__bits_per_word - __dn);
|
||||
if ((*__first2.__seg_ & __m) != (__b >> (__first1.__ctz_ + __ddn)))
|
||||
return false;
|
||||
__first2.__ctz_ = static_cast<unsigned>(__dn);
|
||||
}
|
||||
++__first1.__seg_;
|
||||
// __first1.__ctz_ = 0;
|
||||
}
|
||||
// __first1.__ctz_ == 0;
|
||||
// do middle words
|
||||
unsigned __clz_r = __bits_per_word - __first2.__ctz_;
|
||||
__storage_type __m = ~__storage_type(0) << __first2.__ctz_;
|
||||
for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_) {
|
||||
__storage_type __b = *__first1.__seg_;
|
||||
if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_))
|
||||
return false;
|
||||
++__first2.__seg_;
|
||||
if ((*__first2.__seg_ & ~__m) != (__b >> __clz_r))
|
||||
return false;
|
||||
}
|
||||
// do last word
|
||||
if (__n > 0) {
|
||||
__m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
__storage_type __b = *__first1.__seg_ & __m;
|
||||
__storage_type __dn = std::min(__n, static_cast<difference_type>(__clz_r));
|
||||
__m = (~__storage_type(0) << __first2.__ctz_) & (~__storage_type(0) >> (__clz_r - __dn));
|
||||
if ((*__first2.__seg_ & __m) != (__b << __first2.__ctz_))
|
||||
return false;
|
||||
__first2.__seg_ += (__dn + __first2.__ctz_) / __bits_per_word;
|
||||
__first2.__ctz_ = static_cast<unsigned>((__dn + __first2.__ctz_) % __bits_per_word);
|
||||
__n -= __dn;
|
||||
if (__n > 0) {
|
||||
__m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
if ((*__first2.__seg_ & __m) != (__b >> __dn))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class _Cp, bool _IC1, bool _IC2>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI bool __equal_aligned(
|
||||
__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) {
|
||||
using _It = __bit_iterator<_Cp, _IC1>;
|
||||
using difference_type = typename _It::difference_type;
|
||||
using __storage_type = typename _It::__storage_type;
|
||||
|
||||
const int __bits_per_word = _It::__bits_per_word;
|
||||
difference_type __n = __last1 - __first1;
|
||||
if (__n > 0) {
|
||||
// do first word
|
||||
if (__first1.__ctz_ != 0) {
|
||||
unsigned __clz = __bits_per_word - __first1.__ctz_;
|
||||
difference_type __dn = std::min(static_cast<difference_type>(__clz), __n);
|
||||
__n -= __dn;
|
||||
__storage_type __m = (~__storage_type(0) << __first1.__ctz_) & (~__storage_type(0) >> (__clz - __dn));
|
||||
if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m))
|
||||
return false;
|
||||
++__first2.__seg_;
|
||||
++__first1.__seg_;
|
||||
// __first1.__ctz_ = 0;
|
||||
// __first2.__ctz_ = 0;
|
||||
}
|
||||
// __first1.__ctz_ == 0;
|
||||
// __first2.__ctz_ == 0;
|
||||
// do middle words
|
||||
for (; __n >= __bits_per_word; __n -= __bits_per_word, ++__first1.__seg_, ++__first2.__seg_)
|
||||
if (*__first2.__seg_ != *__first1.__seg_)
|
||||
return false;
|
||||
// do last word
|
||||
if (__n > 0) {
|
||||
__storage_type __m = ~__storage_type(0) >> (__bits_per_word - __n);
|
||||
if ((*__first2.__seg_ & __m) != (*__first1.__seg_ & __m))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class _Cp, bool _IC1, bool _IC2>
|
||||
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
|
||||
equal(__bit_iterator<_Cp, _IC1> __first1, __bit_iterator<_Cp, _IC1> __last1, __bit_iterator<_Cp, _IC2> __first2) {
|
||||
if (__first1.__ctz_ == __first2.__ctz_)
|
||||
return std::__equal_aligned(__first1, __last1, __first2);
|
||||
return std::__equal_unaligned(__first1, __last1, __first2);
|
||||
}
|
||||
|
||||
template <class _Cp, bool _IsConst, typename _Cp::__storage_type>
|
||||
class __bit_iterator {
|
||||
public:
|
||||
|
|
@ -844,6 +329,7 @@ public:
|
|||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 reference operator*() const _NOEXCEPT {
|
||||
_LIBCPP_ASSERT_INTERNAL(__ctz_ < __bits_per_word, "Dereferencing an invalid __bit_iterator.");
|
||||
return __conditional_t<_IsConst, __bit_const_reference<_Cp>, __bit_reference<_Cp> >(
|
||||
__seg_, __storage_type(1) << __ctz_);
|
||||
}
|
||||
|
|
@ -968,7 +454,10 @@ private:
|
|||
_LIBCPP_HIDE_FROM_ABI
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 explicit __bit_iterator(__storage_pointer __s, unsigned __ctz) _NOEXCEPT
|
||||
: __seg_(__s),
|
||||
__ctz_(__ctz) {}
|
||||
__ctz_(__ctz) {
|
||||
_LIBCPP_ASSERT_INTERNAL(
|
||||
__ctz_ < __bits_per_word, "__bit_iterator initialized with an invalid number of trailing zeros.");
|
||||
}
|
||||
|
||||
friend typename _Cp::__self;
|
||||
|
||||
|
|
@ -989,38 +478,59 @@ private:
|
|||
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_unaligned(
|
||||
__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
|
||||
template <class _Dp, bool _IC>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false>
|
||||
copy(__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend pair<__bit_iterator<_Dp, _IC>, __bit_iterator<_Dp, false> >
|
||||
__copy_impl::operator()(
|
||||
__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result) const;
|
||||
template <class _Dp, bool _IC>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_backward_aligned(
|
||||
__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
|
||||
template <class _Dp, bool _IC>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false> __copy_backward_unaligned(
|
||||
__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
|
||||
template <class _Dp, bool _IC>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false>
|
||||
copy_backward(__bit_iterator<_Dp, _IC> __first, __bit_iterator<_Dp, _IC> __last, __bit_iterator<_Dp, false> __result);
|
||||
template <class _AlgPolicy>
|
||||
friend struct __copy_backward_impl;
|
||||
template <class _Cl, class _Cr>
|
||||
friend __bit_iterator<_Cr, false>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Cr, false>
|
||||
__swap_ranges_aligned(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>);
|
||||
template <class _Cl, class _Cr>
|
||||
friend __bit_iterator<_Cr, false>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Cr, false>
|
||||
__swap_ranges_unaligned(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>);
|
||||
template <class _Cl, class _Cr>
|
||||
friend __bit_iterator<_Cr, false>
|
||||
swap_ranges(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>);
|
||||
template <class _Dp>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, false>
|
||||
rotate(__bit_iterator<_Dp, false>, __bit_iterator<_Dp, false>, __bit_iterator<_Dp, false>);
|
||||
template <class _Dp, bool _IC1, bool _IC2>
|
||||
template <class, class _Cl, class _Cr>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend pair<__bit_iterator<_Cl, false>, __bit_iterator<_Cr, false> >
|
||||
__swap_ranges(__bit_iterator<_Cl, false>, __bit_iterator<_Cl, false>, __bit_iterator<_Cr, false>);
|
||||
template <class, class _Dp>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend pair<__bit_iterator<_Dp, false>, __bit_iterator<_Dp, false> >
|
||||
__rotate(__bit_iterator<_Dp, false>, __bit_iterator<_Dp, false>, __bit_iterator<_Dp, false>);
|
||||
template <class _Dp, bool _IsConst1, bool _IsConst2>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
|
||||
__equal_aligned(__bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC2>);
|
||||
template <class _Dp, bool _IC1, bool _IC2>
|
||||
__equal_aligned(__bit_iterator<_Dp, _IsConst1>, __bit_iterator<_Dp, _IsConst1>, __bit_iterator<_Dp, _IsConst2>);
|
||||
template <class _Dp, bool _IsConst1, bool _IsConst2>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
|
||||
__equal_unaligned(__bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC2>);
|
||||
template <class _Dp, bool _IC1, bool _IC2>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
|
||||
equal(__bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC1>, __bit_iterator<_Dp, _IC2>);
|
||||
__equal_unaligned(__bit_iterator<_Dp, _IsConst1>, __bit_iterator<_Dp, _IsConst1>, __bit_iterator<_Dp, _IsConst2>);
|
||||
template <class _Dp,
|
||||
bool _IsConst1,
|
||||
bool _IsConst2,
|
||||
class _BinaryPredicate,
|
||||
__enable_if_t<__desugars_to_v<__equal_tag, _BinaryPredicate, bool, bool>, int> >
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool __equal_iter_impl(
|
||||
__bit_iterator<_Dp, _IsConst1>, __bit_iterator<_Dp, _IsConst1>, __bit_iterator<_Dp, _IsConst2>, _BinaryPredicate);
|
||||
template <class _Dp,
|
||||
bool _IsConst1,
|
||||
bool _IsConst2,
|
||||
class _Pred,
|
||||
class _Proj1,
|
||||
class _Proj2,
|
||||
__enable_if_t<__desugars_to_v<__equal_tag, _Pred, bool, bool> && __is_identity<_Proj1>::value &&
|
||||
__is_identity<_Proj2>::value,
|
||||
int> >
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool __equal_impl(
|
||||
__bit_iterator<_Dp, _IsConst1> __first1,
|
||||
__bit_iterator<_Dp, _IsConst1> __last1,
|
||||
__bit_iterator<_Dp, _IsConst2> __first2,
|
||||
__bit_iterator<_Dp, _IsConst2>,
|
||||
_Pred&,
|
||||
_Proj1&,
|
||||
_Proj2&);
|
||||
template <bool _ToFind, class _Dp, bool _IC>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX20 friend __bit_iterator<_Dp, _IC>
|
||||
__find_bool(__bit_iterator<_Dp, _IC>, typename __size_difference_type_traits<_Dp>::size_type);
|
||||
|
|
|
|||
20
lib/libcxx/include/__charconv/tables.h
vendored
20
lib/libcxx/include/__charconv/tables.h
vendored
|
|
@ -19,16 +19,14 @@
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
|
||||
namespace __itoa {
|
||||
|
||||
inline constexpr char __base_2_lut[64] = {
|
||||
inline _LIBCPP_CONSTEXPR const char __base_2_lut[64] = {
|
||||
'0', '0', '0', '0', '0', '0', '0', '1', '0', '0', '1', '0', '0', '0', '1', '1', '0', '1', '0', '0', '0', '1',
|
||||
'0', '1', '0', '1', '1', '0', '0', '1', '1', '1', '1', '0', '0', '0', '1', '0', '0', '1', '1', '0', '1', '0',
|
||||
'1', '0', '1', '1', '1', '1', '0', '0', '1', '1', '0', '1', '1', '1', '1', '0', '1', '1', '1', '1'};
|
||||
|
||||
inline constexpr char __base_8_lut[128] = {
|
||||
inline _LIBCPP_CONSTEXPR const char __base_8_lut[128] = {
|
||||
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '1', '0', '1', '1', '1', '2',
|
||||
'1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', '2', '5',
|
||||
'2', '6', '2', '7', '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3', '7', '4', '0',
|
||||
|
|
@ -36,7 +34,7 @@ inline constexpr char __base_8_lut[128] = {
|
|||
'5', '4', '5', '5', '5', '6', '5', '7', '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6',
|
||||
'6', '7', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', '7', '5', '7', '6', '7', '7'};
|
||||
|
||||
inline constexpr char __base_16_lut[512] = {
|
||||
inline _LIBCPP_CONSTEXPR const char __base_16_lut[512] = {
|
||||
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', '0', 'a', '0',
|
||||
'b', '0', 'c', '0', 'd', '0', 'e', '0', 'f', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6',
|
||||
'1', '7', '1', '8', '1', '9', '1', 'a', '1', 'b', '1', 'c', '1', 'd', '1', 'e', '1', 'f', '2', '0', '2', '1', '2',
|
||||
|
|
@ -61,7 +59,7 @@ inline constexpr char __base_16_lut[512] = {
|
|||
'1', 'f', '2', 'f', '3', 'f', '4', 'f', '5', 'f', '6', 'f', '7', 'f', '8', 'f', '9', 'f', 'a', 'f', 'b', 'f', 'c',
|
||||
'f', 'd', 'f', 'e', 'f', 'f'};
|
||||
|
||||
inline constexpr uint32_t __pow10_32[10] = {
|
||||
inline _LIBCPP_CONSTEXPR const uint32_t __pow10_32[10] = {
|
||||
UINT32_C(0),
|
||||
UINT32_C(10),
|
||||
UINT32_C(100),
|
||||
|
|
@ -73,7 +71,7 @@ inline constexpr uint32_t __pow10_32[10] = {
|
|||
UINT32_C(100000000),
|
||||
UINT32_C(1000000000)};
|
||||
|
||||
inline constexpr uint64_t __pow10_64[20] = {
|
||||
inline _LIBCPP_CONSTEXPR const uint64_t __pow10_64[20] = {
|
||||
UINT64_C(0),
|
||||
UINT64_C(10),
|
||||
UINT64_C(100),
|
||||
|
|
@ -96,8 +94,8 @@ inline constexpr uint64_t __pow10_64[20] = {
|
|||
UINT64_C(10000000000000000000)};
|
||||
|
||||
# if _LIBCPP_HAS_INT128
|
||||
inline constexpr int __pow10_128_offset = 0;
|
||||
inline constexpr __uint128_t __pow10_128[40] = {
|
||||
inline _LIBCPP_CONSTEXPR const int __pow10_128_offset = 0;
|
||||
inline _LIBCPP_CONSTEXPR const __uint128_t __pow10_128[40] = {
|
||||
UINT64_C(0),
|
||||
UINT64_C(10),
|
||||
UINT64_C(100),
|
||||
|
|
@ -140,7 +138,7 @@ inline constexpr __uint128_t __pow10_128[40] = {
|
|||
(__uint128_t(UINT64_C(10000000000000000000)) * UINT64_C(10000000000000000000)) * 10};
|
||||
# endif
|
||||
|
||||
inline constexpr char __digits_base_10[200] = {
|
||||
inline _LIBCPP_CONSTEXPR const char __digits_base_10[200] = {
|
||||
// clang-format off
|
||||
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0', '7', '0', '8', '0', '9',
|
||||
'1', '0', '1', '1', '1', '2', '1', '3', '1', '4', '1', '5', '1', '6', '1', '7', '1', '8', '1', '9',
|
||||
|
|
@ -156,8 +154,6 @@ inline constexpr char __digits_base_10[200] = {
|
|||
|
||||
} // namespace __itoa
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 17
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___CHARCONV_TABLES
|
||||
|
|
|
|||
32
lib/libcxx/include/__charconv/to_chars_base_10.h
vendored
32
lib/libcxx/include/__charconv/to_chars_base_10.h
vendored
|
|
@ -26,55 +26,53 @@ _LIBCPP_PUSH_MACROS
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
|
||||
namespace __itoa {
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append1(char* __first, uint32_t __value) noexcept {
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append1(char* __first, uint32_t __value) _NOEXCEPT {
|
||||
*__first = '0' + static_cast<char>(__value);
|
||||
return __first + 1;
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append2(char* __first, uint32_t __value) noexcept {
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append2(char* __first, uint32_t __value) _NOEXCEPT {
|
||||
return std::copy_n(&__digits_base_10[__value * 2], 2, __first);
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append3(char* __first, uint32_t __value) noexcept {
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append3(char* __first, uint32_t __value) _NOEXCEPT {
|
||||
return __itoa::__append2(__itoa::__append1(__first, __value / 100), __value % 100);
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append4(char* __first, uint32_t __value) noexcept {
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append4(char* __first, uint32_t __value) _NOEXCEPT {
|
||||
return __itoa::__append2(__itoa::__append2(__first, __value / 100), __value % 100);
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append5(char* __first, uint32_t __value) noexcept {
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append5(char* __first, uint32_t __value) _NOEXCEPT {
|
||||
return __itoa::__append4(__itoa::__append1(__first, __value / 10000), __value % 10000);
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append6(char* __first, uint32_t __value) noexcept {
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append6(char* __first, uint32_t __value) _NOEXCEPT {
|
||||
return __itoa::__append4(__itoa::__append2(__first, __value / 10000), __value % 10000);
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append7(char* __first, uint32_t __value) noexcept {
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append7(char* __first, uint32_t __value) _NOEXCEPT {
|
||||
return __itoa::__append6(__itoa::__append1(__first, __value / 1000000), __value % 1000000);
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append8(char* __first, uint32_t __value) noexcept {
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append8(char* __first, uint32_t __value) _NOEXCEPT {
|
||||
return __itoa::__append6(__itoa::__append2(__first, __value / 1000000), __value % 1000000);
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append9(char* __first, uint32_t __value) noexcept {
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char* __append9(char* __first, uint32_t __value) _NOEXCEPT {
|
||||
return __itoa::__append8(__itoa::__append1(__first, __value / 100000000), __value % 100000000);
|
||||
}
|
||||
|
||||
template <class _Tp>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __append10(char* __first, _Tp __value) noexcept {
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI char* __append10(char* __first, _Tp __value) _NOEXCEPT {
|
||||
return __itoa::__append8(__itoa::__append2(__first, static_cast<uint32_t>(__value / 100000000)),
|
||||
static_cast<uint32_t>(__value % 100000000));
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char*
|
||||
__base_10_u32(char* __first, uint32_t __value) noexcept {
|
||||
__base_10_u32(char* __first, uint32_t __value) _NOEXCEPT {
|
||||
if (__value < 1000000) {
|
||||
if (__value < 10000) {
|
||||
if (__value < 100) {
|
||||
|
|
@ -110,7 +108,7 @@ __base_10_u32(char* __first, uint32_t __value) noexcept {
|
|||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char*
|
||||
__base_10_u64(char* __buffer, uint64_t __value) noexcept {
|
||||
__base_10_u64(char* __buffer, uint64_t __value) _NOEXCEPT {
|
||||
if (__value <= UINT32_MAX)
|
||||
return __itoa::__base_10_u32(__buffer, static_cast<uint32_t>(__value));
|
||||
|
||||
|
|
@ -132,13 +130,13 @@ __base_10_u64(char* __buffer, uint64_t __value) noexcept {
|
|||
/// \note The lookup table contains a partial set of exponents limiting the
|
||||
/// range that can be used. However the range is sufficient for
|
||||
/// \ref __base_10_u128.
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline __uint128_t __pow_10(int __exp) noexcept {
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline __uint128_t __pow_10(int __exp) _NOEXCEPT {
|
||||
_LIBCPP_ASSERT_INTERNAL(__exp >= __pow10_128_offset, "Index out of bounds");
|
||||
return __pow10_128[__exp - __pow10_128_offset];
|
||||
}
|
||||
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI inline char*
|
||||
__base_10_u128(char* __buffer, __uint128_t __value) noexcept {
|
||||
__base_10_u128(char* __buffer, __uint128_t __value) _NOEXCEPT {
|
||||
_LIBCPP_ASSERT_INTERNAL(
|
||||
__value > numeric_limits<uint64_t>::max(), "The optimizations for this algorithm fails when this isn't true.");
|
||||
|
||||
|
|
@ -179,8 +177,6 @@ __base_10_u128(char* __buffer, __uint128_t __value) noexcept {
|
|||
# endif
|
||||
} // namespace __itoa
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 17
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
|
|
|||
|
|
@ -39,16 +39,12 @@ _LIBCPP_PUSH_MACROS
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
|
||||
to_chars_result to_chars(char*, char*, bool, int = 10) = delete;
|
||||
|
||||
template <typename _Tp>
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
|
||||
__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type);
|
||||
|
||||
template <typename _Tp>
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
|
||||
__to_chars_itoa(char* __first, char* __last, _Tp __value, true_type) {
|
||||
auto __x = std::__to_unsigned_like(__value);
|
||||
if (__value < 0 && __first != __last) {
|
||||
|
|
@ -60,7 +56,7 @@ __to_chars_itoa(char* __first, char* __last, _Tp __value, true_type) {
|
|||
}
|
||||
|
||||
template <typename _Tp>
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
|
||||
__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type) {
|
||||
using __tx = __itoa::__traits<_Tp>;
|
||||
auto __diff = __last - __first;
|
||||
|
|
@ -73,7 +69,7 @@ __to_chars_itoa(char* __first, char* __last, _Tp __value, false_type) {
|
|||
|
||||
# if _LIBCPP_HAS_INT128
|
||||
template <>
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
|
||||
__to_chars_itoa(char* __first, char* __last, __uint128_t __value, false_type) {
|
||||
// When the value fits in 64-bits use the 64-bit code path. This reduces
|
||||
// the number of expensive calculations on 128-bit values.
|
||||
|
|
@ -92,20 +88,20 @@ __to_chars_itoa(char* __first, char* __last, __uint128_t __value, false_type) {
|
|||
}
|
||||
# endif
|
||||
|
||||
template <class _Tp>
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
|
||||
__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, false_type);
|
||||
template <class _Tp, __enable_if_t<!is_signed<_Tp>::value, int> = 0>
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
|
||||
__to_chars_integral(char* __first, char* __last, _Tp __value, int __base);
|
||||
|
||||
template <typename _Tp>
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
|
||||
__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, true_type) {
|
||||
template <class _Tp, __enable_if_t<is_signed<_Tp>::value, int> = 0>
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
|
||||
__to_chars_integral(char* __first, char* __last, _Tp __value, int __base) {
|
||||
auto __x = std::__to_unsigned_like(__value);
|
||||
if (__value < 0 && __first != __last) {
|
||||
*__first++ = '-';
|
||||
__x = std::__complement(__x);
|
||||
}
|
||||
|
||||
return std::__to_chars_integral(__first, __last, __x, __base, false_type());
|
||||
return std::__to_chars_integral(__first, __last, __x, __base);
|
||||
}
|
||||
|
||||
namespace __itoa {
|
||||
|
|
@ -116,15 +112,14 @@ struct _LIBCPP_HIDDEN __integral;
|
|||
template <>
|
||||
struct _LIBCPP_HIDDEN __integral<2> {
|
||||
template <typename _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept {
|
||||
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int __width(_Tp __value) _NOEXCEPT {
|
||||
// If value == 0 still need one digit. If the value != this has no
|
||||
// effect since the code scans for the most significant bit set. (Note
|
||||
// that __libcpp_clz doesn't work for 0.)
|
||||
return numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1);
|
||||
// effect since the code scans for the most significant bit set.
|
||||
return numeric_limits<_Tp>::digits - std::__countl_zero(__value | 1);
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static __to_chars_result
|
||||
__to_chars(char* __first, char* __last, _Tp __value) {
|
||||
ptrdiff_t __cap = __last - __first;
|
||||
int __n = __width(__value);
|
||||
|
|
@ -152,15 +147,14 @@ struct _LIBCPP_HIDDEN __integral<2> {
|
|||
template <>
|
||||
struct _LIBCPP_HIDDEN __integral<8> {
|
||||
template <typename _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept {
|
||||
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int __width(_Tp __value) _NOEXCEPT {
|
||||
// If value == 0 still need one digit. If the value != this has no
|
||||
// effect since the code scans for the most significat bit set. (Note
|
||||
// that __libcpp_clz doesn't work for 0.)
|
||||
return ((numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1)) + 2) / 3;
|
||||
// effect since the code scans for the most significat bit set.
|
||||
return ((numeric_limits<_Tp>::digits - std::__countl_zero(__value | 1)) + 2) / 3;
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static __to_chars_result
|
||||
__to_chars(char* __first, char* __last, _Tp __value) {
|
||||
ptrdiff_t __cap = __last - __first;
|
||||
int __n = __width(__value);
|
||||
|
|
@ -188,15 +182,14 @@ struct _LIBCPP_HIDDEN __integral<8> {
|
|||
template <>
|
||||
struct _LIBCPP_HIDDEN __integral<16> {
|
||||
template <typename _Tp>
|
||||
_LIBCPP_HIDE_FROM_ABI static constexpr int __width(_Tp __value) noexcept {
|
||||
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int __width(_Tp __value) _NOEXCEPT {
|
||||
// If value == 0 still need one digit. If the value != this has no
|
||||
// effect since the code scans for the most significat bit set. (Note
|
||||
// that __libcpp_clz doesn't work for 0.)
|
||||
return (numeric_limits<_Tp>::digits - std::__libcpp_clz(__value | 1) + 3) / 4;
|
||||
// effect since the code scans for the most significat bit set.
|
||||
return (numeric_limits<_Tp>::digits - std::__countl_zero(__value | 1) + 3) / 4;
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static to_chars_result
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static __to_chars_result
|
||||
__to_chars(char* __first, char* __last, _Tp __value) {
|
||||
ptrdiff_t __cap = __last - __first;
|
||||
int __n = __width(__value);
|
||||
|
|
@ -235,13 +228,13 @@ _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_widt
|
|||
}
|
||||
|
||||
template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) >= sizeof(unsigned)), int> = 0>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
|
||||
__to_chars_integral(char* __first, char* __last, _Tp __value) {
|
||||
return __itoa::__integral<_Base>::__to_chars(__first, __last, __value);
|
||||
}
|
||||
|
||||
template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) < sizeof(unsigned)), int> = 0>
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
|
||||
__to_chars_integral(char* __first, char* __last, _Tp __value) {
|
||||
return std::__to_chars_integral<_Base>(__first, __last, static_cast<unsigned>(__value));
|
||||
}
|
||||
|
|
@ -272,9 +265,9 @@ _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_widt
|
|||
__libcpp_unreachable();
|
||||
}
|
||||
|
||||
template <typename _Tp>
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
|
||||
__to_chars_integral(char* __first, char* __last, _Tp __value, int __base, false_type) {
|
||||
template <class _Tp, __enable_if_t<!is_signed<_Tp>::value, int> >
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
|
||||
__to_chars_integral(char* __first, char* __last, _Tp __value, int __base) {
|
||||
if (__base == 10) [[likely]]
|
||||
return std::__to_chars_itoa(__first, __last, __value, false_type());
|
||||
|
||||
|
|
@ -302,6 +295,28 @@ __to_chars_integral(char* __first, char* __last, _Tp __value, int __base, false_
|
|||
return {__last, errc(0)};
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 char __hex_to_upper(char __c) {
|
||||
switch (__c) {
|
||||
case 'a':
|
||||
return 'A';
|
||||
case 'b':
|
||||
return 'B';
|
||||
case 'c':
|
||||
return 'C';
|
||||
case 'd':
|
||||
return 'D';
|
||||
case 'e':
|
||||
return 'E';
|
||||
case 'f':
|
||||
return 'F';
|
||||
}
|
||||
return __c;
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
|
||||
to_chars_result to_chars(char*, char*, bool, int = 10) = delete;
|
||||
|
||||
template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
|
||||
to_chars(char* __first, char* __last, _Tp __value) {
|
||||
|
|
@ -316,7 +331,7 @@ to_chars(char* __first, char* __last, _Tp __value, int __base) {
|
|||
_LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]");
|
||||
|
||||
using _Type = __make_32_64_or_128_bit_t<_Tp>;
|
||||
return std::__to_chars_integral(__first, __last, static_cast<_Type>(__value), __base, is_signed<_Tp>());
|
||||
return std::__to_chars_integral(__first, __last, static_cast<_Type>(__value), __base);
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 17
|
||||
|
|
|
|||
|
|
@ -34,6 +34,15 @@ struct _LIBCPP_EXPORTED_FROM_ABI to_chars_result {
|
|||
|
||||
#endif // _LIBCPP_STD_VER >= 17
|
||||
|
||||
struct __to_chars_result {
|
||||
char* __ptr;
|
||||
errc __ec;
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr operator to_chars_result() { return {__ptr, __ec}; }
|
||||
#endif
|
||||
};
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___CHARCONV_TO_CHARS_RESULT_H
|
||||
|
|
|
|||
30
lib/libcxx/include/__charconv/traits.h
vendored
30
lib/libcxx/include/__charconv/traits.h
vendored
|
|
@ -15,6 +15,7 @@
|
|||
#include <__charconv/tables.h>
|
||||
#include <__charconv/to_chars_base_10.h>
|
||||
#include <__config>
|
||||
#include <__memory/addressof.h>
|
||||
#include <__type_traits/enable_if.h>
|
||||
#include <__type_traits/is_unsigned.h>
|
||||
#include <cstdint>
|
||||
|
|
@ -29,8 +30,6 @@ _LIBCPP_PUSH_MACROS
|
|||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
|
||||
namespace __itoa {
|
||||
|
||||
template <typename _Tp, typename = void>
|
||||
|
|
@ -44,12 +43,9 @@ struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) <= sizeof(uin
|
|||
///
|
||||
/// The algorithm is based on
|
||||
/// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
|
||||
/// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that
|
||||
/// function requires its input to have at least one bit set the value of
|
||||
/// zero is set to one. This means the first element of the lookup table is
|
||||
/// zero.
|
||||
/// Instead of using IntegerLogBase2 it uses __countl_zero.
|
||||
static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) {
|
||||
auto __t = (32 - std::__libcpp_clz(static_cast<type>(__v | 1))) * 1233 >> 12;
|
||||
auto __t = (32 - std::__countl_zero(static_cast<type>(__v | 1))) * 1233 >> 12;
|
||||
return __t - (__v < __itoa::__pow10_32[__t]) + 1;
|
||||
}
|
||||
|
||||
|
|
@ -70,12 +66,9 @@ struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) == sizeof(uin
|
|||
///
|
||||
/// The algorithm is based on
|
||||
/// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
|
||||
/// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that
|
||||
/// function requires its input to have at least one bit set the value of
|
||||
/// zero is set to one. This means the first element of the lookup table is
|
||||
/// zero.
|
||||
/// Instead of using IntegerLogBase2 it uses __countl_zero.
|
||||
static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) {
|
||||
auto __t = (64 - std::__libcpp_clz(static_cast<type>(__v | 1))) * 1233 >> 12;
|
||||
auto __t = (64 - std::__countl_zero(static_cast<type>(__v | 1))) * 1233 >> 12;
|
||||
return __t - (__v < __itoa::__pow10_64[__t]) + 1;
|
||||
}
|
||||
|
||||
|
|
@ -97,15 +90,12 @@ struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) == sizeof(__u
|
|||
///
|
||||
/// The algorithm is based on
|
||||
/// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
|
||||
/// Instead of using IntegerLogBase2 it uses __libcpp_clz. Since that
|
||||
/// function requires its input to have at least one bit set the value of
|
||||
/// zero is set to one. This means the first element of the lookup table is
|
||||
/// zero.
|
||||
/// Instead of using IntegerLogBase2 it uses __countl_zero.
|
||||
static _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __width(_Tp __v) {
|
||||
_LIBCPP_ASSERT_INTERNAL(
|
||||
__v > numeric_limits<uint64_t>::max(), "The optimizations for this algorithm fail when this isn't true.");
|
||||
// There's always a bit set in the upper 64-bits.
|
||||
auto __t = (128 - std::__libcpp_clz(static_cast<uint64_t>(__v >> 64))) * 1233 >> 12;
|
||||
auto __t = (128 - std::__countl_zero(static_cast<uint64_t>(__v >> 64))) * 1233 >> 12;
|
||||
_LIBCPP_ASSERT_INTERNAL(__t >= __itoa::__pow10_128_offset, "Index out of bounds");
|
||||
// __t is adjusted since the lookup table misses the lower entries.
|
||||
return __t - (__v < __itoa::__pow10_128[__t - __itoa::__pow10_128_offset]) + 1;
|
||||
|
|
@ -142,7 +132,7 @@ __mul_overflowed(unsigned short __a, _Tp __b, unsigned short& __r) {
|
|||
template <typename _Tp>
|
||||
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool __mul_overflowed(_Tp __a, _Tp __b, _Tp& __r) {
|
||||
static_assert(is_unsigned<_Tp>::value, "");
|
||||
return __builtin_mul_overflow(__a, __b, &__r);
|
||||
return __builtin_mul_overflow(__a, __b, std::addressof(__r));
|
||||
}
|
||||
|
||||
template <typename _Tp, typename _Up>
|
||||
|
|
@ -152,7 +142,7 @@ inline _LIBCPP_HIDE_FROM_ABI bool _LIBCPP_CONSTEXPR_SINCE_CXX23 __mul_overflowed
|
|||
|
||||
template <typename _Tp>
|
||||
struct _LIBCPP_HIDDEN __traits : __traits_base<_Tp> {
|
||||
static constexpr int digits = numeric_limits<_Tp>::digits10 + 1;
|
||||
static _LIBCPP_CONSTEXPR const int digits = numeric_limits<_Tp>::digits10 + 1;
|
||||
using __traits_base<_Tp>::__pow;
|
||||
using typename __traits_base<_Tp>::type;
|
||||
|
||||
|
|
@ -191,8 +181,6 @@ inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _Tp __complement(_Tp
|
|||
return _Tp(~__x + 1);
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 17
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
|
|
|||
34
lib/libcxx/include/__chrono/convert_to_tm.h
vendored
34
lib/libcxx/include/__chrono/convert_to_tm.h
vendored
|
|
@ -15,6 +15,7 @@
|
|||
#include <__chrono/day.h>
|
||||
#include <__chrono/duration.h>
|
||||
#include <__chrono/file_clock.h>
|
||||
#include <__chrono/gps_clock.h>
|
||||
#include <__chrono/hh_mm_ss.h>
|
||||
#include <__chrono/local_info.h>
|
||||
#include <__chrono/month.h>
|
||||
|
|
@ -23,6 +24,7 @@
|
|||
#include <__chrono/statically_widen.h>
|
||||
#include <__chrono/sys_info.h>
|
||||
#include <__chrono/system_clock.h>
|
||||
#include <__chrono/tai_clock.h>
|
||||
#include <__chrono/time_point.h>
|
||||
#include <__chrono/utc_clock.h>
|
||||
#include <__chrono/weekday.h>
|
||||
|
|
@ -35,6 +37,7 @@
|
|||
#include <__config>
|
||||
#include <__format/format_error.h>
|
||||
#include <__memory/addressof.h>
|
||||
#include <__type_traits/common_type.h>
|
||||
#include <__type_traits/is_convertible.h>
|
||||
#include <__type_traits/is_specialization.h>
|
||||
#include <cstdint>
|
||||
|
|
@ -112,6 +115,21 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(chrono::utc_time<_Duration> __tp) {
|
|||
return __result;
|
||||
}
|
||||
|
||||
template <class _Tm, class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(chrono::tai_time<_Duration> __tp) {
|
||||
using _Rp = common_type_t<_Duration, chrono::seconds>;
|
||||
// The time between the TAI epoch (1958-01-01) and UNIX epoch (1970-01-01).
|
||||
// This avoids leap second conversion when going from TAI to UTC.
|
||||
// (It also avoids issues when the date is before the UTC epoch.)
|
||||
constexpr chrono::seconds __offset{4383 * 24 * 60 * 60};
|
||||
return std::__convert_to_tm<_Tm>(chrono::sys_time<_Rp>{__tp.time_since_epoch() - __offset});
|
||||
}
|
||||
|
||||
template <class _Tm, class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(chrono::gps_time<_Duration> __tp) {
|
||||
return std::__convert_to_tm<_Tm>(chrono::utc_clock::to_sys(chrono::gps_clock::to_utc(__tp)));
|
||||
}
|
||||
|
||||
# endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
||||
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
|
||||
|
||||
|
|
@ -125,20 +143,16 @@ _LIBCPP_HIDE_FROM_ABI _Tm __convert_to_tm(const _ChronoT& __value) {
|
|||
# endif
|
||||
|
||||
if constexpr (__is_time_point<_ChronoT>) {
|
||||
if constexpr (same_as<typename _ChronoT::clock, chrono::system_clock>)
|
||||
return std::__convert_to_tm<_Tm>(__value);
|
||||
# if _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
|
||||
# if _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
||||
else if constexpr (same_as<typename _ChronoT::clock, chrono::utc_clock>)
|
||||
return std::__convert_to_tm<_Tm>(__value);
|
||||
# endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
||||
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
|
||||
else if constexpr (same_as<typename _ChronoT::clock, chrono::file_clock>)
|
||||
if constexpr (same_as<typename _ChronoT::clock, chrono::file_clock>)
|
||||
return std::__convert_to_tm<_Tm>(_ChronoT::clock::to_sys(__value));
|
||||
else if constexpr (same_as<typename _ChronoT::clock, chrono::local_t>)
|
||||
return std::__convert_to_tm<_Tm>(chrono::sys_time<typename _ChronoT::duration>{__value.time_since_epoch()});
|
||||
else
|
||||
else {
|
||||
// Note that some clocks have specializations __convert_to_tm for their
|
||||
// time_point. These don't need to be added here. They do not trigger
|
||||
// this assert.
|
||||
static_assert(sizeof(_ChronoT) == 0, "TODO: Add the missing clock specialization");
|
||||
}
|
||||
} else if constexpr (chrono::__is_duration_v<_ChronoT>) {
|
||||
// [time.format]/6
|
||||
// ... However, if a flag refers to a "time of day" (e.g. %H, %I, %p,
|
||||
|
|
|
|||
10
lib/libcxx/include/__chrono/duration.h
vendored
10
lib/libcxx/include/__chrono/duration.h
vendored
|
|
@ -32,7 +32,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
namespace chrono {
|
||||
|
||||
template <class _Rep, class _Period = ratio<1> >
|
||||
class _LIBCPP_TEMPLATE_VIS duration;
|
||||
class duration;
|
||||
|
||||
template <class _Tp>
|
||||
inline const bool __is_duration_v = false;
|
||||
|
|
@ -52,7 +52,7 @@ inline const bool __is_duration_v<const volatile duration<_Rep, _Period> > = tru
|
|||
} // namespace chrono
|
||||
|
||||
template <class _Rep1, class _Period1, class _Rep2, class _Period2>
|
||||
struct _LIBCPP_TEMPLATE_VIS common_type<chrono::duration<_Rep1, _Period1>, chrono::duration<_Rep2, _Period2> > {
|
||||
struct common_type<chrono::duration<_Rep1, _Period1>, chrono::duration<_Rep2, _Period2> > {
|
||||
typedef chrono::duration<typename common_type<_Rep1, _Rep2>::type, __ratio_gcd<_Period1, _Period2> > type;
|
||||
};
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration duration_cast(const d
|
|||
}
|
||||
|
||||
template <class _Rep>
|
||||
struct _LIBCPP_TEMPLATE_VIS treat_as_floating_point : is_floating_point<_Rep> {};
|
||||
struct treat_as_floating_point : is_floating_point<_Rep> {};
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
template <class _Rep>
|
||||
|
|
@ -115,7 +115,7 @@ inline constexpr bool treat_as_floating_point_v = treat_as_floating_point<_Rep>:
|
|||
#endif
|
||||
|
||||
template <class _Rep>
|
||||
struct _LIBCPP_TEMPLATE_VIS duration_values {
|
||||
struct duration_values {
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Rep zero() _NOEXCEPT { return _Rep(0); }
|
||||
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Rep max() _NOEXCEPT { return numeric_limits<_Rep>::max(); }
|
||||
|
|
@ -156,7 +156,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _ToDuration round(const duration<
|
|||
// duration
|
||||
|
||||
template <class _Rep, class _Period>
|
||||
class _LIBCPP_TEMPLATE_VIS duration {
|
||||
class duration {
|
||||
static_assert(!__is_duration_v<_Rep>, "A duration representation can not be a duration");
|
||||
static_assert(__is_ratio_v<_Period>, "Second template parameter of duration must be a std::ratio");
|
||||
static_assert(_Period::num > 0, "duration period must be positive");
|
||||
|
|
|
|||
78
lib/libcxx/include/__chrono/formatter.h
vendored
78
lib/libcxx/include/__chrono/formatter.h
vendored
|
|
@ -21,6 +21,7 @@
|
|||
# include <__chrono/day.h>
|
||||
# include <__chrono/duration.h>
|
||||
# include <__chrono/file_clock.h>
|
||||
# include <__chrono/gps_clock.h>
|
||||
# include <__chrono/hh_mm_ss.h>
|
||||
# include <__chrono/local_info.h>
|
||||
# include <__chrono/month.h>
|
||||
|
|
@ -31,6 +32,7 @@
|
|||
# include <__chrono/statically_widen.h>
|
||||
# include <__chrono/sys_info.h>
|
||||
# include <__chrono/system_clock.h>
|
||||
# include <__chrono/tai_clock.h>
|
||||
# include <__chrono/time_point.h>
|
||||
# include <__chrono/utc_clock.h>
|
||||
# include <__chrono/weekday.h>
|
||||
|
|
@ -48,12 +50,14 @@
|
|||
# include <__format/formatter.h>
|
||||
# include <__format/parser_std_format_spec.h>
|
||||
# include <__format/write_escaped.h>
|
||||
# include <__iterator/istreambuf_iterator.h>
|
||||
# include <__iterator/ostreambuf_iterator.h>
|
||||
# include <__locale_dir/time.h>
|
||||
# include <__memory/addressof.h>
|
||||
# include <__type_traits/is_specialization.h>
|
||||
# include <cmath>
|
||||
# include <ctime>
|
||||
# include <limits>
|
||||
# include <locale>
|
||||
# include <sstream>
|
||||
# include <string_view>
|
||||
|
||||
|
|
@ -232,9 +236,13 @@ _LIBCPP_HIDE_FROM_ABI __time_zone __convert_to_time_zone([[maybe_unused]] const
|
|||
if constexpr (same_as<_Tp, chrono::sys_info>)
|
||||
return {__value.abbrev, __value.offset};
|
||||
# if _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
|
||||
else if constexpr (__is_time_point<_Tp> && requires { requires same_as<typename _Tp::clock, chrono::tai_clock>; })
|
||||
return {"TAI", chrono::seconds{0}};
|
||||
else if constexpr (__is_time_point<_Tp> && requires { requires same_as<typename _Tp::clock, chrono::gps_clock>; })
|
||||
return {"GPS", chrono::seconds{0}};
|
||||
else if constexpr (__is_specialization_v<_Tp, chrono::zoned_time>)
|
||||
return __formatter::__convert_to_time_zone(__value.get_info());
|
||||
# endif
|
||||
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
|
||||
else
|
||||
# endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
||||
return {"UTC", chrono::seconds{0}};
|
||||
|
|
@ -312,7 +320,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs(
|
|||
case _CharT('T'):
|
||||
__facet.put(
|
||||
{__sstr}, __sstr, _CharT(' '), std::addressof(__t), std::to_address(__s), std::to_address(__it + 1));
|
||||
if constexpr (__use_fraction<_Tp>())
|
||||
if constexpr (__formatter::__use_fraction<_Tp>())
|
||||
__formatter::__format_sub_seconds(__sstr, __value);
|
||||
break;
|
||||
|
||||
|
|
@ -375,7 +383,7 @@ _LIBCPP_HIDE_FROM_ABI void __format_chrono_using_chrono_specs(
|
|||
break;
|
||||
|
||||
case _CharT('O'):
|
||||
if constexpr (__use_fraction<_Tp>()) {
|
||||
if constexpr (__formatter::__use_fraction<_Tp>()) {
|
||||
// Handle OS using the normal representation for the non-fractional
|
||||
// part. There seems to be no locale information regarding how the
|
||||
// fractional part should be formatted.
|
||||
|
|
@ -692,7 +700,7 @@ __format_chrono(const _Tp& __value,
|
|||
} // namespace __formatter
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS __formatter_chrono {
|
||||
struct __formatter_chrono {
|
||||
public:
|
||||
template <class _ParseContext>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator
|
||||
|
|
@ -710,7 +718,7 @@ public:
|
|||
};
|
||||
|
||||
template <class _Duration, __fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::sys_time<_Duration>, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::sys_time<_Duration>, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -724,7 +732,29 @@ public:
|
|||
# if _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
||||
|
||||
template <class _Duration, __fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::utc_time<_Duration>, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::utc_time<_Duration>, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
template <class _ParseContext>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) {
|
||||
return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__clock);
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Duration, __fmt_char_type _CharT>
|
||||
struct formatter<chrono::tai_time<_Duration>, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
template <class _ParseContext>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) {
|
||||
return _Base::__parse(__ctx, __format_spec::__fields_chrono, __format_spec::__flags::__clock);
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Duration, __fmt_char_type _CharT>
|
||||
struct formatter<chrono::gps_time<_Duration>, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -738,7 +768,7 @@ public:
|
|||
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
|
||||
|
||||
template <class _Duration, __fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::file_time<_Duration>, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::file_time<_Duration>, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -749,7 +779,7 @@ public:
|
|||
};
|
||||
|
||||
template <class _Duration, __fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::local_time<_Duration>, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::local_time<_Duration>, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -783,7 +813,7 @@ public:
|
|||
};
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::day, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::day, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -794,7 +824,7 @@ public:
|
|||
};
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::month, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::month, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -805,7 +835,7 @@ public:
|
|||
};
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::year, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::year, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -816,7 +846,7 @@ public:
|
|||
};
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::weekday, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::weekday, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -827,7 +857,7 @@ public:
|
|||
};
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::weekday_indexed, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::weekday_indexed, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -838,7 +868,7 @@ public:
|
|||
};
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::weekday_last, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::weekday_last, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -849,7 +879,7 @@ public:
|
|||
};
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::month_day, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::month_day, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -860,7 +890,7 @@ public:
|
|||
};
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::month_day_last, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::month_day_last, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -871,7 +901,7 @@ public:
|
|||
};
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::month_weekday, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::month_weekday, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -882,7 +912,7 @@ public:
|
|||
};
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::month_weekday_last, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::month_weekday_last, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -893,7 +923,7 @@ public:
|
|||
};
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::year_month, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::year_month, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -904,7 +934,7 @@ public:
|
|||
};
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::year_month_day, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::year_month_day, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -915,7 +945,7 @@ public:
|
|||
};
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::year_month_day_last, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::year_month_day_last, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -926,7 +956,7 @@ public:
|
|||
};
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::year_month_weekday, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::year_month_weekday, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
@ -937,7 +967,7 @@ public:
|
|||
};
|
||||
|
||||
template <__fmt_char_type _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<chrono::year_month_weekday_last, _CharT> : public __formatter_chrono<_CharT> {
|
||||
struct formatter<chrono::year_month_weekday_last, _CharT> : public __formatter_chrono<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __formatter_chrono<_CharT>;
|
||||
|
||||
|
|
|
|||
90
lib/libcxx/include/__chrono/gps_clock.h
vendored
Normal file
90
lib/libcxx/include/__chrono/gps_clock.h
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___CHRONO_GPS_CLOCK_H
|
||||
#define _LIBCPP___CHRONO_GPS_CLOCK_H
|
||||
|
||||
#include <version>
|
||||
// Enable the contents of the header only when libc++ was built with experimental features enabled.
|
||||
#if _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
||||
|
||||
# include <__assert>
|
||||
# include <__chrono/duration.h>
|
||||
# include <__chrono/time_point.h>
|
||||
# include <__chrono/utc_clock.h>
|
||||
# include <__config>
|
||||
# include <__type_traits/common_type.h>
|
||||
|
||||
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
# endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
# include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
# if _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
|
||||
|
||||
namespace chrono {
|
||||
|
||||
class gps_clock;
|
||||
|
||||
template <class _Duration>
|
||||
using gps_time = time_point<gps_clock, _Duration>;
|
||||
using gps_seconds = gps_time<seconds>;
|
||||
|
||||
class gps_clock {
|
||||
public:
|
||||
using rep = utc_clock::rep;
|
||||
using period = utc_clock::period;
|
||||
using duration = chrono::duration<rep, period>;
|
||||
using time_point = chrono::time_point<gps_clock>;
|
||||
static constexpr bool is_steady = false; // The utc_clock is not steady.
|
||||
|
||||
// The static difference between UTC and GPS time as specified in the Standard.
|
||||
static constexpr chrono::seconds __offset{315964809};
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static time_point now() { return from_utc(utc_clock::now()); }
|
||||
|
||||
template <class _Duration>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static utc_time<common_type_t<_Duration, seconds>>
|
||||
to_utc(const gps_time<_Duration>& __time) noexcept {
|
||||
using _Rp = common_type_t<_Duration, seconds>;
|
||||
_Duration __time_since_epoch = __time.time_since_epoch();
|
||||
_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__time_since_epoch >= utc_time<_Rp>::min().time_since_epoch() + __offset,
|
||||
"the GPS to UTC conversion would underflow");
|
||||
|
||||
return utc_time<_Rp>{__time_since_epoch + __offset};
|
||||
}
|
||||
|
||||
template <class _Duration>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static gps_time<common_type_t<_Duration, seconds>>
|
||||
from_utc(const utc_time<_Duration>& __time) noexcept {
|
||||
using _Rp = common_type_t<_Duration, seconds>;
|
||||
_Duration __time_since_epoch = __time.time_since_epoch();
|
||||
_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__time_since_epoch <= utc_time<_Rp>::max().time_since_epoch() - __offset,
|
||||
"the UTC to GPS conversion would overflow");
|
||||
|
||||
return gps_time<_Rp>{__time_since_epoch - __offset};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace chrono
|
||||
|
||||
# endif // _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM &&
|
||||
// _LIBCPP_HAS_LOCALIZATION
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
||||
|
||||
#endif // _LIBCPP___CHRONO_GPS_CLOCK_H
|
||||
14
lib/libcxx/include/__chrono/ostream.h
vendored
14
lib/libcxx/include/__chrono/ostream.h
vendored
|
|
@ -18,6 +18,7 @@
|
|||
# include <__chrono/day.h>
|
||||
# include <__chrono/duration.h>
|
||||
# include <__chrono/file_clock.h>
|
||||
# include <__chrono/gps_clock.h>
|
||||
# include <__chrono/hh_mm_ss.h>
|
||||
# include <__chrono/local_info.h>
|
||||
# include <__chrono/month.h>
|
||||
|
|
@ -26,6 +27,7 @@
|
|||
# include <__chrono/statically_widen.h>
|
||||
# include <__chrono/sys_info.h>
|
||||
# include <__chrono/system_clock.h>
|
||||
# include <__chrono/tai_clock.h>
|
||||
# include <__chrono/utc_clock.h>
|
||||
# include <__chrono/weekday.h>
|
||||
# include <__chrono/year.h>
|
||||
|
|
@ -71,6 +73,18 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const utc_time<_Duration>& __tp
|
|||
return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
|
||||
operator<<(basic_ostream<_CharT, _Traits>& __os, const tai_time<_Duration>& __tp) {
|
||||
return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Duration>
|
||||
_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
|
||||
operator<<(basic_ostream<_CharT, _Traits>& __os, const gps_time<_Duration>& __tp) {
|
||||
return __os << std::format(__os.getloc(), _LIBCPP_STATICALLY_WIDEN(_CharT, "{:L%F %T}"), __tp);
|
||||
}
|
||||
|
||||
# endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
||||
# endif // _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr void __validate_time_zone(__flags __flags) {
|
|||
}
|
||||
|
||||
template <class _CharT>
|
||||
class _LIBCPP_TEMPLATE_VIS __parser_chrono {
|
||||
class __parser_chrono {
|
||||
using _ConstIterator _LIBCPP_NODEBUG = typename basic_format_parse_context<_CharT>::const_iterator;
|
||||
|
||||
public:
|
||||
|
|
|
|||
108
lib/libcxx/include/__chrono/tai_clock.h
vendored
Normal file
108
lib/libcxx/include/__chrono/tai_clock.h
vendored
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___CHRONO_TAI_CLOCK_H
|
||||
#define _LIBCPP___CHRONO_TAI_CLOCK_H
|
||||
|
||||
#include <version>
|
||||
// Enable the contents of the header only when libc++ was built with experimental features enabled.
|
||||
#if _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
||||
|
||||
# include <__assert>
|
||||
# include <__chrono/duration.h>
|
||||
# include <__chrono/time_point.h>
|
||||
# include <__chrono/utc_clock.h>
|
||||
# include <__config>
|
||||
# include <__type_traits/common_type.h>
|
||||
|
||||
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
# endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
# include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
# if _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM && _LIBCPP_HAS_LOCALIZATION
|
||||
|
||||
namespace chrono {
|
||||
|
||||
class tai_clock;
|
||||
|
||||
template <class _Duration>
|
||||
using tai_time = time_point<tai_clock, _Duration>;
|
||||
using tai_seconds = tai_time<seconds>;
|
||||
|
||||
// [time.clock.tai.overview]/1
|
||||
// The clock tai_clock measures seconds since 1958-01-01 00:00:00 and is
|
||||
// offset 10s ahead of UTC at this date. That is, 1958-01-01 00:00:00 TAI is
|
||||
// equivalent to 1957-12-31 23:59:50 UTC. Leap seconds are not inserted into
|
||||
// TAI. Therefore every time a leap second is inserted into UTC, UTC shifts
|
||||
// another second with respect to TAI. For example by 2000-01-01 there had
|
||||
// been 22 positive and 0 negative leap seconds inserted so 2000-01-01
|
||||
// 00:00:00 UTC is equivalent to 2000-01-01 00:00:32 TAI (22s plus the
|
||||
// initial 10s offset).
|
||||
//
|
||||
// Note this does not specify what the UTC offset before 1958-01-01 00:00:00
|
||||
// TAI is, nor does it follow the "real" TAI clock between 1958-01-01 and the
|
||||
// start of the UTC epoch. So while the member functions are fully specified in
|
||||
// the standard, they do not technically follow the "real-world" TAI clock with
|
||||
// 100% accuracy.
|
||||
//
|
||||
// https://koka-lang.github.io/koka/doc/std_time_utc.html contains more
|
||||
// information and references.
|
||||
class tai_clock {
|
||||
public:
|
||||
using rep = utc_clock::rep;
|
||||
using period = utc_clock::period;
|
||||
using duration = chrono::duration<rep, period>;
|
||||
using time_point = chrono::time_point<tai_clock>;
|
||||
static constexpr bool is_steady = false; // The utc_clock is not steady.
|
||||
|
||||
// The static difference between UTC and TAI time.
|
||||
static constexpr chrono::seconds __offset{378691210};
|
||||
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static time_point now() { return from_utc(utc_clock::now()); }
|
||||
|
||||
template <class _Duration>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static utc_time<common_type_t<_Duration, seconds>>
|
||||
to_utc(const tai_time<_Duration>& __time) noexcept {
|
||||
using _Rp = common_type_t<_Duration, seconds>;
|
||||
_Duration __time_since_epoch = __time.time_since_epoch();
|
||||
_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__time_since_epoch >= utc_time<_Rp>::min().time_since_epoch() + __offset,
|
||||
"the TAI to UTC conversion would underflow");
|
||||
|
||||
return utc_time<_Rp>{__time_since_epoch - __offset};
|
||||
}
|
||||
|
||||
template <class _Duration>
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static tai_time<common_type_t<_Duration, seconds>>
|
||||
from_utc(const utc_time<_Duration>& __time) noexcept {
|
||||
using _Rp = common_type_t<_Duration, seconds>;
|
||||
_Duration __time_since_epoch = __time.time_since_epoch();
|
||||
_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(__time_since_epoch <= utc_time<_Rp>::max().time_since_epoch() - __offset,
|
||||
"the UTC to TAI conversion would overflow");
|
||||
|
||||
return tai_time<_Rp>{__time_since_epoch + __offset};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace chrono
|
||||
|
||||
# endif // _LIBCPP_STD_VER >= 20 && _LIBCPP_HAS_TIME_ZONE_DATABASE && _LIBCPP_HAS_FILESYSTEM &&
|
||||
// _LIBCPP_HAS_LOCALIZATION
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP_HAS_EXPERIMENTAL_TZDB
|
||||
|
||||
#endif // _LIBCPP___CHRONO_TAI_CLOCK_H
|
||||
18
lib/libcxx/include/__chrono/time_point.h
vendored
18
lib/libcxx/include/__chrono/time_point.h
vendored
|
|
@ -31,7 +31,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
namespace chrono {
|
||||
|
||||
template <class _Clock, class _Duration = typename _Clock::duration>
|
||||
class _LIBCPP_TEMPLATE_VIS time_point {
|
||||
class time_point {
|
||||
static_assert(__is_duration_v<_Duration>, "Second template parameter of time_point must be a std::chrono::duration");
|
||||
|
||||
public:
|
||||
|
|
@ -58,6 +58,19 @@ public:
|
|||
|
||||
// arithmetic
|
||||
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr time_point& operator++() {
|
||||
++__d_;
|
||||
return *this;
|
||||
}
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr time_point operator++(int) { return time_point{__d_++}; }
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr time_point& operator--() {
|
||||
--__d_;
|
||||
return *this;
|
||||
}
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr time_point operator--(int) { return time_point{__d_--}; }
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 time_point& operator+=(const duration& __d) {
|
||||
__d_ += __d;
|
||||
return *this;
|
||||
|
|
@ -76,8 +89,7 @@ public:
|
|||
} // namespace chrono
|
||||
|
||||
template <class _Clock, class _Duration1, class _Duration2>
|
||||
struct _LIBCPP_TEMPLATE_VIS
|
||||
common_type<chrono::time_point<_Clock, _Duration1>, chrono::time_point<_Clock, _Duration2> > {
|
||||
struct common_type<chrono::time_point<_Clock, _Duration1>, chrono::time_point<_Clock, _Duration2> > {
|
||||
typedef chrono::time_point<_Clock, typename common_type<_Duration1, _Duration2>::type> type;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ __compute_comp_type(const _ClassifyCompCategory (&__types)[_Size]) {
|
|||
template <class... _Ts, bool _False = false>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr auto __get_comp_type() {
|
||||
using _CCC = _ClassifyCompCategory;
|
||||
constexpr _CCC __type_kinds[] = {_StrongOrd, __type_to_enum<_Ts>()...};
|
||||
constexpr _CCC __type_kinds[] = {_StrongOrd, __comp_detail::__type_to_enum<_Ts>()...};
|
||||
constexpr _CCC __cat = __comp_detail::__compute_comp_type(__type_kinds);
|
||||
if constexpr (__cat == _None)
|
||||
return void();
|
||||
|
|
@ -72,8 +72,8 @@ _LIBCPP_HIDE_FROM_ABI constexpr auto __get_comp_type() {
|
|||
|
||||
// [cmp.common], common comparison category type
|
||||
template <class... _Ts>
|
||||
struct _LIBCPP_TEMPLATE_VIS common_comparison_category {
|
||||
using type = decltype(__comp_detail::__get_comp_type<_Ts...>());
|
||||
struct common_comparison_category {
|
||||
using type _LIBCPP_NODEBUG = decltype(__comp_detail::__get_comp_type<_Ts...>());
|
||||
};
|
||||
|
||||
template <class... _Ts>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
|
||||
struct _LIBCPP_TEMPLATE_VIS compare_three_way {
|
||||
struct compare_three_way {
|
||||
template <class _T1, class _T2>
|
||||
requires three_way_comparable_with<_T1, _T2>
|
||||
constexpr _LIBCPP_HIDE_FROM_ABI auto operator()(_T1&& __t, _T2&& __u) const
|
||||
|
|
|
|||
|
|
@ -29,12 +29,12 @@ struct _LIBCPP_HIDE_FROM_ABI __compare_three_way_result<
|
|||
_Tp,
|
||||
_Up,
|
||||
decltype(std::declval<__make_const_lvalue_ref<_Tp>>() <=> std::declval<__make_const_lvalue_ref<_Up>>(), void())> {
|
||||
using type = decltype(std::declval<__make_const_lvalue_ref<_Tp>>() <=> std::declval<__make_const_lvalue_ref<_Up>>());
|
||||
using type _LIBCPP_NODEBUG =
|
||||
decltype(std::declval<__make_const_lvalue_ref<_Tp>>() <=> std::declval<__make_const_lvalue_ref<_Up>>());
|
||||
};
|
||||
|
||||
template <class _Tp, class _Up = _Tp>
|
||||
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS compare_three_way_result
|
||||
: __compare_three_way_result<_Tp, _Up, void> {};
|
||||
struct _LIBCPP_NO_SPECIALIZATIONS compare_three_way_result : __compare_three_way_result<_Tp, _Up, void> {};
|
||||
|
||||
template <class _Tp, class _Up = _Tp>
|
||||
using compare_three_way_result_t = typename compare_three_way_result<_Tp, _Up>::type;
|
||||
|
|
|
|||
13
lib/libcxx/include/__concepts/arithmetic.h
vendored
13
lib/libcxx/include/__concepts/arithmetic.h
vendored
|
|
@ -13,8 +13,6 @@
|
|||
#include <__type_traits/is_floating_point.h>
|
||||
#include <__type_traits/is_integral.h>
|
||||
#include <__type_traits/is_signed.h>
|
||||
#include <__type_traits/is_signed_integer.h>
|
||||
#include <__type_traits/is_unsigned_integer.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
|
|
@ -38,17 +36,6 @@ concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>;
|
|||
template <class _Tp>
|
||||
concept floating_point = is_floating_point_v<_Tp>;
|
||||
|
||||
// Concept helpers for the internal type traits for the fundamental types.
|
||||
|
||||
template <class _Tp>
|
||||
concept __libcpp_unsigned_integer = __libcpp_is_unsigned_integer<_Tp>::value;
|
||||
|
||||
template <class _Tp>
|
||||
concept __libcpp_signed_integer = __libcpp_is_signed_integer<_Tp>::value;
|
||||
|
||||
template <class _Tp>
|
||||
concept __libcpp_integer = __libcpp_unsigned_integer<_Tp> || __libcpp_signed_integer<_Tp>;
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
#include <__type_traits/is_class.h>
|
||||
#include <__type_traits/is_enum.h>
|
||||
#include <__type_traits/is_union.h>
|
||||
#include <__type_traits/remove_cvref.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
|
|
|
|||
2
lib/libcxx/include/__concepts/common_with.h
vendored
2
lib/libcxx/include/__concepts/common_with.h
vendored
|
|
@ -12,7 +12,7 @@
|
|||
#include <__concepts/common_reference_with.h>
|
||||
#include <__concepts/same_as.h>
|
||||
#include <__config>
|
||||
#include <__type_traits/add_lvalue_reference.h>
|
||||
#include <__type_traits/add_reference.h>
|
||||
#include <__type_traits/common_reference.h>
|
||||
#include <__type_traits/common_type.h>
|
||||
#include <__utility/declval.h>
|
||||
|
|
|
|||
1
lib/libcxx/include/__concepts/swappable.h
vendored
1
lib/libcxx/include/__concepts/swappable.h
vendored
|
|
@ -22,7 +22,6 @@
|
|||
#include <__utility/exchange.h>
|
||||
#include <__utility/forward.h>
|
||||
#include <__utility/move.h>
|
||||
#include <__utility/swap.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
|
|
|
|||
|
|
@ -39,60 +39,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
_LIBCPP_DECLARE_STRONG_ENUM(cv_status){no_timeout, timeout};
|
||||
_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(cv_status)
|
||||
|
||||
class _LIBCPP_EXPORTED_FROM_ABI condition_variable {
|
||||
__libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
|
||||
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default;
|
||||
|
||||
# if _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION
|
||||
~condition_variable() = default;
|
||||
# else
|
||||
~condition_variable();
|
||||
# endif
|
||||
|
||||
condition_variable(const condition_variable&) = delete;
|
||||
condition_variable& operator=(const condition_variable&) = delete;
|
||||
|
||||
void notify_one() _NOEXCEPT;
|
||||
void notify_all() _NOEXCEPT;
|
||||
|
||||
void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
|
||||
template <class _Predicate>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS void wait(unique_lock<mutex>& __lk, _Predicate __pred);
|
||||
|
||||
template <class _Clock, class _Duration>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status
|
||||
wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t);
|
||||
|
||||
template <class _Clock, class _Duration, class _Predicate>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS bool
|
||||
wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred);
|
||||
|
||||
template <class _Rep, class _Period>
|
||||
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS cv_status
|
||||
wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d);
|
||||
|
||||
template <class _Rep, class _Period, class _Predicate>
|
||||
bool _LIBCPP_HIDE_FROM_ABI
|
||||
wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred);
|
||||
|
||||
typedef __libcpp_condvar_t* native_handle_type;
|
||||
_LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__cv_; }
|
||||
|
||||
private:
|
||||
void
|
||||
__do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
|
||||
# if _LIBCPP_HAS_COND_CLOCKWAIT
|
||||
_LIBCPP_HIDE_FROM_ABI void
|
||||
__do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<chrono::steady_clock, chrono::nanoseconds>) _NOEXCEPT;
|
||||
# endif
|
||||
template <class _Clock>
|
||||
_LIBCPP_HIDE_FROM_ABI void
|
||||
__do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT;
|
||||
};
|
||||
#endif // _LIBCPP_HAS_THREADS
|
||||
|
||||
template <class _Rep, class _Period, __enable_if_t<is_floating_point<_Rep>::value, int> = 0>
|
||||
inline _LIBCPP_HIDE_FROM_ABI chrono::nanoseconds __safe_nanosecond_cast(chrono::duration<_Rep, _Period> __d) {
|
||||
using namespace chrono;
|
||||
|
|
@ -140,15 +86,35 @@ inline _LIBCPP_HIDE_FROM_ABI chrono::nanoseconds __safe_nanosecond_cast(chrono::
|
|||
return nanoseconds(__result);
|
||||
}
|
||||
|
||||
#if _LIBCPP_HAS_THREADS
|
||||
class _LIBCPP_EXPORTED_FROM_ABI condition_variable {
|
||||
__libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
|
||||
|
||||
public:
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default;
|
||||
|
||||
# if _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION
|
||||
~condition_variable() = default;
|
||||
# else
|
||||
~condition_variable();
|
||||
# endif
|
||||
|
||||
condition_variable(const condition_variable&) = delete;
|
||||
condition_variable& operator=(const condition_variable&) = delete;
|
||||
|
||||
void notify_one() _NOEXCEPT;
|
||||
void notify_all() _NOEXCEPT;
|
||||
|
||||
void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
|
||||
|
||||
template <class _Predicate>
|
||||
void condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) {
|
||||
_LIBCPP_HIDE_FROM_ABI void wait(unique_lock<mutex>& __lk, _Predicate __pred) {
|
||||
while (!__pred())
|
||||
wait(__lk);
|
||||
}
|
||||
|
||||
template <class _Clock, class _Duration>
|
||||
cv_status condition_variable::wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t) {
|
||||
_LIBCPP_HIDE_FROM_ABI cv_status
|
||||
wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t) {
|
||||
using namespace chrono;
|
||||
using __clock_tp_ns = time_point<_Clock, nanoseconds>;
|
||||
|
||||
|
|
@ -163,8 +129,8 @@ cv_status condition_variable::wait_until(unique_lock<mutex>& __lk, const chrono:
|
|||
}
|
||||
|
||||
template <class _Clock, class _Duration, class _Predicate>
|
||||
bool condition_variable::wait_until(
|
||||
unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred) {
|
||||
_LIBCPP_HIDE_FROM_ABI bool
|
||||
wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t, _Predicate __pred) {
|
||||
while (!__pred()) {
|
||||
if (wait_until(__lk, __t) == cv_status::timeout)
|
||||
return __pred();
|
||||
|
|
@ -173,7 +139,7 @@ bool condition_variable::wait_until(
|
|||
}
|
||||
|
||||
template <class _Rep, class _Period>
|
||||
cv_status condition_variable::wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d) {
|
||||
_LIBCPP_HIDE_FROM_ABI cv_status wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d) {
|
||||
using namespace chrono;
|
||||
if (__d <= __d.zero())
|
||||
return cv_status::timeout;
|
||||
|
|
@ -199,6 +165,28 @@ cv_status condition_variable::wait_for(unique_lock<mutex>& __lk, const chrono::d
|
|||
return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : cv_status::timeout;
|
||||
}
|
||||
|
||||
template <class _Rep, class _Period, class _Predicate>
|
||||
bool _LIBCPP_HIDE_FROM_ABI
|
||||
wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred);
|
||||
|
||||
typedef __libcpp_condvar_t* native_handle_type;
|
||||
_LIBCPP_HIDE_FROM_ABI native_handle_type native_handle() { return &__cv_; }
|
||||
|
||||
private:
|
||||
void
|
||||
__do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<chrono::system_clock, chrono::nanoseconds>) _NOEXCEPT;
|
||||
# if _LIBCPP_HAS_COND_CLOCKWAIT
|
||||
_LIBCPP_HIDE_FROM_ABI void
|
||||
__do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<chrono::steady_clock, chrono::nanoseconds>) _NOEXCEPT;
|
||||
# endif
|
||||
template <class _Clock>
|
||||
_LIBCPP_HIDE_FROM_ABI void
|
||||
__do_timed_wait(unique_lock<mutex>& __lk, chrono::time_point<_Clock, chrono::nanoseconds>) _NOEXCEPT;
|
||||
};
|
||||
#endif // _LIBCPP_HAS_THREADS
|
||||
|
||||
#if _LIBCPP_HAS_THREADS
|
||||
|
||||
template <class _Rep, class _Period, class _Predicate>
|
||||
inline bool
|
||||
condition_variable::wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d, _Predicate __pred) {
|
||||
|
|
@ -210,7 +198,7 @@ inline void condition_variable::__do_timed_wait(
|
|||
unique_lock<mutex>& __lk, chrono::time_point<chrono::steady_clock, chrono::nanoseconds> __tp) _NOEXCEPT {
|
||||
using namespace chrono;
|
||||
if (!__lk.owns_lock())
|
||||
__throw_system_error(EPERM, "condition_variable::timed wait: mutex not locked");
|
||||
std::__throw_system_error(EPERM, "condition_variable::timed wait: mutex not locked");
|
||||
nanoseconds __d = __tp.time_since_epoch();
|
||||
timespec __ts;
|
||||
seconds __s = duration_cast<seconds>(__d);
|
||||
|
|
@ -225,7 +213,7 @@ inline void condition_variable::__do_timed_wait(
|
|||
}
|
||||
int __ec = pthread_cond_clockwait(&__cv_, __lk.mutex()->native_handle(), CLOCK_MONOTONIC, &__ts);
|
||||
if (__ec != 0 && __ec != ETIMEDOUT)
|
||||
__throw_system_error(__ec, "condition_variable timed_wait failed");
|
||||
std::__throw_system_error(__ec, "condition_variable timed_wait failed");
|
||||
}
|
||||
# endif // _LIBCPP_HAS_COND_CLOCKWAIT
|
||||
|
||||
|
|
|
|||
348
lib/libcxx/include/__config
vendored
348
lib/libcxx/include/__config
vendored
|
|
@ -28,7 +28,7 @@
|
|||
// _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM.
|
||||
// Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 17.0.1 == 17.00.01), _LIBCPP_VERSION is
|
||||
// defined to XXYYZZ.
|
||||
# define _LIBCPP_VERSION 200100
|
||||
# define _LIBCPP_VERSION 210100
|
||||
|
||||
# define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y
|
||||
# define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y)
|
||||
|
|
@ -38,11 +38,47 @@
|
|||
# define _LIBCPP_FREESTANDING
|
||||
# endif
|
||||
|
||||
// NOLINTNEXTLINE(libcpp-cpp-version-check)
|
||||
# if __cplusplus < 201103L
|
||||
# define _LIBCPP_CXX03_LANG
|
||||
# endif
|
||||
|
||||
# if __has_feature(experimental_library)
|
||||
# ifndef _LIBCPP_ENABLE_EXPERIMENTAL
|
||||
# define _LIBCPP_ENABLE_EXPERIMENTAL
|
||||
# endif
|
||||
# endif
|
||||
|
||||
// Incomplete features get their own specific disabling flags. This makes it
|
||||
// easier to grep for target specific flags once the feature is complete.
|
||||
# if defined(_LIBCPP_ENABLE_EXPERIMENTAL) || defined(_LIBCPP_BUILDING_LIBRARY)
|
||||
# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 1
|
||||
# else
|
||||
# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 0
|
||||
# endif
|
||||
|
||||
# define _LIBCPP_HAS_EXPERIMENTAL_PSTL _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
|
||||
# define _LIBCPP_HAS_EXPERIMENTAL_TZDB _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
|
||||
# define _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
|
||||
# define _LIBCPP_HAS_EXPERIMENTAL_HARDENING_OBSERVE_SEMANTIC _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
|
||||
|
||||
// HARDENING {
|
||||
|
||||
// TODO: Remove in LLVM 21. We're making this an error to catch folks who might not have migrated.
|
||||
# ifdef _LIBCPP_ENABLE_ASSERTIONS
|
||||
# error "_LIBCPP_ENABLE_ASSERTIONS has been removed, please use _LIBCPP_HARDENING_MODE instead"
|
||||
// TODO(LLVM 23): Remove this. We're making these an error to catch folks who might not have migrated.
|
||||
// Since hardening went through several changes (many of which impacted user-facing macros),
|
||||
// we're keeping these checks around for a bit longer than usual. Failure to properly configure
|
||||
// hardening results in checks being dropped silently, which is a pretty big deal.
|
||||
# if defined(_LIBCPP_ENABLE_ASSERTIONS)
|
||||
# error "_LIBCPP_ENABLE_ASSERTIONS has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
|
||||
# endif
|
||||
# if defined(_LIBCPP_ENABLE_HARDENED_MODE)
|
||||
# error "_LIBCPP_ENABLE_HARDENED_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
|
||||
# endif
|
||||
# if defined(_LIBCPP_ENABLE_SAFE_MODE)
|
||||
# error "_LIBCPP_ENABLE_SAFE_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
|
||||
# endif
|
||||
# if defined(_LIBCPP_ENABLE_DEBUG_MODE)
|
||||
# error "_LIBCPP_ENABLE_DEBUG_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)"
|
||||
# endif
|
||||
|
||||
// The library provides the macro `_LIBCPP_HARDENING_MODE` which can be set to one of the following values:
|
||||
|
|
@ -147,16 +183,53 @@ _LIBCPP_HARDENING_MODE_EXTENSIVE, \
|
|||
_LIBCPP_HARDENING_MODE_DEBUG
|
||||
# endif
|
||||
|
||||
// Hardening assertion semantics generally mirror the evaluation semantics of C++26 Contracts:
|
||||
// - `ignore` evaluates the assertion but doesn't do anything if it fails (note that it differs from the Contracts
|
||||
// `ignore` semantic which wouldn't evaluate the assertion at all);
|
||||
// - `observe` logs an error (indicating, if possible, that the error is fatal) and continues execution;
|
||||
// - `quick-enforce` terminates the program as fast as possible (via trapping);
|
||||
// - `enforce` logs an error and then terminates the program.
|
||||
//
|
||||
// Notes:
|
||||
// - Continuing execution after a hardening check fails results in undefined behavior; the `observe` semantic is meant
|
||||
// to make adopting hardening easier but should not be used outside of this scenario;
|
||||
// - C++26 wording for Library Hardening precludes a conforming Hardened implementation from using the Contracts
|
||||
// `ignore` semantic when evaluating hardened preconditions in the Library. Libc++ allows using this semantic for
|
||||
// hardened preconditions, however, be aware that using `ignore` does not produce a conforming "Hardened"
|
||||
// implementation, unlike the other semantics above.
|
||||
// clang-format off
|
||||
# define _LIBCPP_ASSERTION_SEMANTIC_IGNORE (1 << 1)
|
||||
# define _LIBCPP_ASSERTION_SEMANTIC_OBSERVE (1 << 2)
|
||||
# define _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE (1 << 3)
|
||||
# define _LIBCPP_ASSERTION_SEMANTIC_ENFORCE (1 << 4)
|
||||
// clang-format on
|
||||
|
||||
// Allow users to define an arbitrary assertion semantic; otherwise, use the default mapping from modes to semantics.
|
||||
// The default is for production-capable modes to use `quick-enforce` (i.e., trap) and for the `debug` mode to use
|
||||
// `enforce` (i.e., log and abort).
|
||||
# ifndef _LIBCPP_ASSERTION_SEMANTIC
|
||||
|
||||
# if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG
|
||||
# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_ENFORCE
|
||||
# else
|
||||
# define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE
|
||||
# endif
|
||||
|
||||
# else
|
||||
# if !_LIBCPP_HAS_EXPERIMENTAL_LIBRARY
|
||||
# error "Assertion semantics are an experimental feature."
|
||||
# endif
|
||||
# if defined(_LIBCPP_CXX03_LANG)
|
||||
# error "Assertion semantics are not available in the C++03 mode."
|
||||
# endif
|
||||
|
||||
# endif // _LIBCPP_ASSERTION_SEMANTIC
|
||||
|
||||
// } HARDENING
|
||||
|
||||
# define _LIBCPP_TOSTRING2(x) #x
|
||||
# define _LIBCPP_TOSTRING(x) _LIBCPP_TOSTRING2(x)
|
||||
|
||||
// NOLINTNEXTLINE(libcpp-cpp-version-check)
|
||||
# if __cplusplus < 201103L
|
||||
# define _LIBCPP_CXX03_LANG
|
||||
# endif
|
||||
|
||||
# ifndef __has_constexpr_builtin
|
||||
# define __has_constexpr_builtin(x) 0
|
||||
# endif
|
||||
|
|
@ -190,24 +263,6 @@ _LIBCPP_HARDENING_MODE_DEBUG
|
|||
# define _LIBCPP_ABI_VCRUNTIME
|
||||
# endif
|
||||
|
||||
# if __has_feature(experimental_library)
|
||||
# ifndef _LIBCPP_ENABLE_EXPERIMENTAL
|
||||
# define _LIBCPP_ENABLE_EXPERIMENTAL
|
||||
# endif
|
||||
# endif
|
||||
|
||||
// Incomplete features get their own specific disabling flags. This makes it
|
||||
// easier to grep for target specific flags once the feature is complete.
|
||||
# if defined(_LIBCPP_ENABLE_EXPERIMENTAL) || defined(_LIBCPP_BUILDING_LIBRARY)
|
||||
# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 1
|
||||
# else
|
||||
# define _LIBCPP_HAS_EXPERIMENTAL_LIBRARY 0
|
||||
# endif
|
||||
|
||||
# define _LIBCPP_HAS_EXPERIMENTAL_PSTL _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
|
||||
# define _LIBCPP_HAS_EXPERIMENTAL_TZDB _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
|
||||
# define _LIBCPP_HAS_EXPERIMENTAL_SYNCSTREAM _LIBCPP_HAS_EXPERIMENTAL_LIBRARY
|
||||
|
||||
# if defined(__MVS__)
|
||||
# include <features.h> // for __NATIVE_ASCII_F
|
||||
# endif
|
||||
|
|
@ -319,41 +374,14 @@ typedef __char32_t char32_t;
|
|||
|
||||
# define _LIBCPP_PREFERRED_ALIGNOF(_Tp) __alignof(_Tp)
|
||||
|
||||
// Objective-C++ features (opt-in)
|
||||
# if __has_feature(objc_arc)
|
||||
# define _LIBCPP_HAS_OBJC_ARC 1
|
||||
# else
|
||||
# define _LIBCPP_HAS_OBJC_ARC 0
|
||||
# endif
|
||||
|
||||
# if __has_feature(objc_arc_weak)
|
||||
# define _LIBCPP_HAS_OBJC_ARC_WEAK 1
|
||||
# else
|
||||
# define _LIBCPP_HAS_OBJC_ARC_WEAK 0
|
||||
# endif
|
||||
|
||||
# if __has_extension(blocks)
|
||||
# define _LIBCPP_HAS_EXTENSION_BLOCKS 1
|
||||
# else
|
||||
# define _LIBCPP_HAS_EXTENSION_BLOCKS 0
|
||||
# endif
|
||||
|
||||
# if _LIBCPP_HAS_EXTENSION_BLOCKS && defined(__APPLE__)
|
||||
# if __has_extension(blocks) && defined(__APPLE__)
|
||||
# define _LIBCPP_HAS_BLOCKS_RUNTIME 1
|
||||
# else
|
||||
# define _LIBCPP_HAS_BLOCKS_RUNTIME 0
|
||||
# endif
|
||||
|
||||
# if __has_feature(address_sanitizer)
|
||||
# define _LIBCPP_HAS_ASAN 1
|
||||
# else
|
||||
# define _LIBCPP_HAS_ASAN 0
|
||||
# endif
|
||||
|
||||
# define _LIBCPP_ALWAYS_INLINE __attribute__((__always_inline__))
|
||||
|
||||
# define _LIBCPP_DISABLE_EXTENSION_WARNING __extension__
|
||||
|
||||
# if defined(_LIBCPP_OBJECT_FORMAT_COFF)
|
||||
|
||||
# ifdef _DLL
|
||||
|
|
@ -363,35 +391,30 @@ typedef __char32_t char32_t;
|
|||
# endif
|
||||
|
||||
# if defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) || (defined(__MINGW32__) && !defined(_LIBCPP_BUILDING_LIBRARY))
|
||||
# define _LIBCPP_DLL_VIS
|
||||
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS
|
||||
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
|
||||
# define _LIBCPP_OVERRIDABLE_FUNC_VIS
|
||||
# define _LIBCPP_EXPORTED_FROM_ABI
|
||||
# elif defined(_LIBCPP_BUILDING_LIBRARY)
|
||||
# define _LIBCPP_DLL_VIS __declspec(dllexport)
|
||||
# if defined(__MINGW32__)
|
||||
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_DLL_VIS
|
||||
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __declspec(dllexport)
|
||||
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
|
||||
# else
|
||||
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS
|
||||
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS _LIBCPP_DLL_VIS
|
||||
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __declspec(dllexport)
|
||||
# endif
|
||||
# define _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_DLL_VIS
|
||||
# define _LIBCPP_OVERRIDABLE_FUNC_VIS __declspec(dllexport)
|
||||
# define _LIBCPP_EXPORTED_FROM_ABI __declspec(dllexport)
|
||||
# else
|
||||
# define _LIBCPP_DLL_VIS __declspec(dllimport)
|
||||
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS _LIBCPP_DLL_VIS
|
||||
# define _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __declspec(dllimport)
|
||||
# define _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS
|
||||
# define _LIBCPP_OVERRIDABLE_FUNC_VIS
|
||||
# define _LIBCPP_EXPORTED_FROM_ABI __declspec(dllimport)
|
||||
# endif
|
||||
|
||||
# define _LIBCPP_HIDDEN
|
||||
# define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
|
||||
# define _LIBCPP_TEMPLATE_VIS
|
||||
# define _LIBCPP_TEMPLATE_DATA_VIS
|
||||
# define _LIBCPP_TYPE_VISIBILITY_DEFAULT
|
||||
# define _LIBCPP_NAMESPACE_VISIBILITY
|
||||
|
||||
# else
|
||||
|
||||
|
|
@ -412,24 +435,12 @@ typedef __char32_t char32_t;
|
|||
# define _LIBCPP_OVERRIDABLE_FUNC_VIS _LIBCPP_VISIBILITY("default")
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
|
||||
// The inline should be removed once PR32114 is resolved
|
||||
# define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS inline _LIBCPP_HIDDEN
|
||||
# else
|
||||
# define _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
|
||||
# endif
|
||||
|
||||
// GCC doesn't support the type_visibility attribute, so we have to keep the visibility attribute on templates
|
||||
# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) && !__has_attribute(__type_visibility__)
|
||||
# define _LIBCPP_TEMPLATE_VIS __attribute__((__visibility__("default")))
|
||||
# else
|
||||
# define _LIBCPP_TEMPLATE_VIS
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS) && __has_attribute(__type_visibility__)
|
||||
# define _LIBCPP_TYPE_VISIBILITY_DEFAULT __attribute__((__type_visibility__("default")))
|
||||
# define _LIBCPP_NAMESPACE_VISIBILITY __attribute__((__type_visibility__("default")))
|
||||
# elif !defined(_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
|
||||
# define _LIBCPP_NAMESPACE_VISIBILITY __attribute__((__visibility__("default")))
|
||||
# else
|
||||
# define _LIBCPP_TYPE_VISIBILITY_DEFAULT
|
||||
# define _LIBCPP_NAMESPACE_VISIBILITY
|
||||
# endif
|
||||
|
||||
# endif // defined(_LIBCPP_OBJECT_FORMAT_COFF)
|
||||
|
|
@ -549,24 +560,17 @@ typedef __char32_t char32_t;
|
|||
# define _LIBCPP_HIDE_FROM_ABI_AFTER_V1 _LIBCPP_HIDE_FROM_ABI
|
||||
# endif
|
||||
|
||||
// TODO: Remove this workaround once we drop support for Clang 16
|
||||
# if __has_warning("-Wc++23-extensions")
|
||||
# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++23-extensions")
|
||||
# else
|
||||
# define _LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++2b-extensions")
|
||||
# endif
|
||||
|
||||
// Clang modules take a significant compile time hit when pushing and popping diagnostics.
|
||||
// Since all the headers are marked as system headers in the modulemap, we can simply disable this
|
||||
// pushing and popping when building with clang modules.
|
||||
# if !__has_feature(modules)
|
||||
// Since all the headers are marked as system headers unless _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER is defined, we can
|
||||
// simply disable this pushing and popping when _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER isn't defined.
|
||||
# ifdef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
|
||||
# define _LIBCPP_PUSH_EXTENSION_DIAGNOSTICS \
|
||||
_LIBCPP_DIAGNOSTIC_PUSH \
|
||||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++11-extensions") \
|
||||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \
|
||||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \
|
||||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \
|
||||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED_CXX23_EXTENSION \
|
||||
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc++23-extensions") \
|
||||
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++14-extensions") \
|
||||
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++17-extensions") \
|
||||
_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wc++20-extensions") \
|
||||
|
|
@ -577,15 +581,27 @@ typedef __char32_t char32_t;
|
|||
# define _LIBCPP_POP_EXTENSION_DIAGNOSTICS
|
||||
# endif
|
||||
|
||||
// Inline namespaces are available in Clang/GCC/MSVC regardless of C++ dialect.
|
||||
// clang-format off
|
||||
# define _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_PUSH_EXTENSION_DIAGNOSTICS \
|
||||
namespace _LIBCPP_TYPE_VISIBILITY_DEFAULT std { \
|
||||
inline namespace _LIBCPP_ABI_NAMESPACE {
|
||||
# define _LIBCPP_END_NAMESPACE_STD }} _LIBCPP_POP_EXTENSION_DIAGNOSTICS
|
||||
|
||||
#define _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL namespace std { namespace experimental {
|
||||
#define _LIBCPP_END_NAMESPACE_EXPERIMENTAL }}
|
||||
// The unversioned namespace is used when we want to be ABI compatible with other standard libraries in some way. There
|
||||
// are two main categories where that's the case:
|
||||
// - Historically, we have made exception types ABI compatible with libstdc++ to allow throwing them between libstdc++
|
||||
// and libc++. This is not used anymore for new exception types, since there is no use-case for it anymore.
|
||||
// - Types and functions which are used by the compiler are in the unversioned namespace, since the compiler has to know
|
||||
// their mangling without the appropriate declaration in some cases.
|
||||
// If it's not clear whether using the unversioned namespace is the correct thing to do, it's not. The versioned
|
||||
// namespace (_LIBCPP_BEGIN_NAMESPACE_STD) should almost always be used.
|
||||
# define _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD \
|
||||
_LIBCPP_PUSH_EXTENSION_DIAGNOSTICS namespace _LIBCPP_NAMESPACE_VISIBILITY std {
|
||||
|
||||
# define _LIBCPP_END_UNVERSIONED_NAMESPACE_STD } _LIBCPP_POP_EXTENSION_DIAGNOSTICS
|
||||
|
||||
# define _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD inline namespace _LIBCPP_ABI_NAMESPACE {
|
||||
# define _LIBCPP_END_NAMESPACE_STD } _LIBCPP_END_UNVERSIONED_NAMESPACE_STD
|
||||
|
||||
// TODO: This should really be in the versioned namespace
|
||||
#define _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD namespace experimental {
|
||||
#define _LIBCPP_END_NAMESPACE_EXPERIMENTAL } _LIBCPP_END_UNVERSIONED_NAMESPACE_STD
|
||||
|
||||
#define _LIBCPP_BEGIN_NAMESPACE_LFTS _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL inline namespace fundamentals_v1 {
|
||||
#define _LIBCPP_END_NAMESPACE_LFTS } _LIBCPP_END_NAMESPACE_EXPERIMENTAL
|
||||
|
|
@ -663,7 +679,10 @@ typedef __char32_t char32_t;
|
|||
# if (defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101500) || \
|
||||
(defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 130000)
|
||||
__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 130000) || \
|
||||
(defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \
|
||||
__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 60000) || \
|
||||
(defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 130000)
|
||||
# define _LIBCPP_HAS_C11_ALIGNED_ALLOC 0
|
||||
# else
|
||||
# define _LIBCPP_HAS_C11_ALIGNED_ALLOC 1
|
||||
|
|
@ -675,10 +694,6 @@ typedef __char32_t char32_t;
|
|||
# define _LIBCPP_HAS_C11_ALIGNED_ALLOC 1
|
||||
# endif
|
||||
|
||||
# if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
# define _LIBCPP_HAS_DEFAULTRUNELOCALE
|
||||
# endif
|
||||
|
||||
# if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
# define _LIBCPP_WCTYPE_IS_MASK
|
||||
# endif
|
||||
|
|
@ -741,8 +756,10 @@ typedef __char32_t char32_t;
|
|||
|
||||
# if _LIBCPP_STD_VER >= 26
|
||||
# define _LIBCPP_DEPRECATED_IN_CXX26 _LIBCPP_DEPRECATED
|
||||
# define _LIBCPP_DEPRECATED_IN_CXX26_(m) _LIBCPP_DEPRECATED_(m)
|
||||
# else
|
||||
# define _LIBCPP_DEPRECATED_IN_CXX26
|
||||
# define _LIBCPP_DEPRECATED_IN_CXX26_(m)
|
||||
# endif
|
||||
|
||||
# if _LIBCPP_HAS_CHAR8_T
|
||||
|
|
@ -937,23 +954,6 @@ typedef __char32_t char32_t;
|
|||
# define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
|
||||
# endif
|
||||
|
||||
// Work around the attribute handling in clang. When both __declspec and
|
||||
// __attribute__ are present, the processing goes awry preventing the definition
|
||||
// of the types. In MinGW mode, __declspec evaluates to __attribute__, and thus
|
||||
// combining the two does work.
|
||||
# if defined(_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS) && defined(__clang__) && \
|
||||
__has_attribute(acquire_capability) && !defined(_MSC_VER)
|
||||
# define _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS 1
|
||||
# else
|
||||
# define _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS 0
|
||||
# endif
|
||||
|
||||
# if _LIBCPP_HAS_THREAD_SAFETY_ANNOTATIONS
|
||||
# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x) __attribute__((x))
|
||||
# else
|
||||
# define _LIBCPP_THREAD_SAFETY_ANNOTATION(x)
|
||||
# endif
|
||||
|
||||
# if _LIBCPP_STD_VER >= 20
|
||||
# define _LIBCPP_CONSTINIT constinit
|
||||
# elif __has_attribute(__require_constant_initialization__)
|
||||
|
|
@ -1064,9 +1064,8 @@ typedef __char32_t char32_t;
|
|||
# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "")
|
||||
# endif
|
||||
|
||||
// TODO(varconst): currently, there are bugs in Clang's intrinsics when handling Objective-C++ `id`, so don't use
|
||||
// compiler intrinsics in the Objective-C++ mode.
|
||||
# ifdef __OBJC__
|
||||
// TODO(LLVM 22): Remove the workaround
|
||||
# if defined(__OBJC__) && (!defined(_LIBCPP_CLANG_VER) || _LIBCPP_CLANG_VER < 2001)
|
||||
# define _LIBCPP_WORKAROUND_OBJCXX_COMPILER_INTRINSICS
|
||||
# endif
|
||||
|
||||
|
|
@ -1119,26 +1118,28 @@ typedef __char32_t char32_t;
|
|||
|
||||
// Optional attributes - these are useful for a better QoI, but not required to be available
|
||||
|
||||
# define _LIBCPP_NOALIAS __attribute__((__malloc__))
|
||||
# define _LIBCPP_NODEBUG [[__gnu__::__nodebug__]]
|
||||
# define _LIBCPP_NO_SANITIZE(...) __attribute__((__no_sanitize__(__VA_ARGS__)))
|
||||
# define _LIBCPP_INIT_PRIORITY_MAX __attribute__((__init_priority__(100)))
|
||||
# define _LIBCPP_ATTRIBUTE_FORMAT(archetype, format_string_index, first_format_arg_index) \
|
||||
__attribute__((__format__(archetype, format_string_index, first_format_arg_index)))
|
||||
# define _LIBCPP_PACKED __attribute__((__packed__))
|
||||
|
||||
# if __has_attribute(__no_sanitize__) && !defined(_LIBCPP_COMPILER_GCC)
|
||||
# define _LIBCPP_NO_CFI __attribute__((__no_sanitize__("cfi")))
|
||||
# else
|
||||
# define _LIBCPP_NO_CFI
|
||||
# endif
|
||||
|
||||
# if __has_attribute(__malloc__)
|
||||
# define _LIBCPP_NOALIAS __attribute__((__malloc__))
|
||||
# else
|
||||
# define _LIBCPP_NOALIAS
|
||||
# endif
|
||||
|
||||
# if __has_attribute(__using_if_exists__)
|
||||
# define _LIBCPP_USING_IF_EXISTS __attribute__((__using_if_exists__))
|
||||
# else
|
||||
# define _LIBCPP_USING_IF_EXISTS
|
||||
# endif
|
||||
|
||||
# if __has_attribute(__no_destroy__)
|
||||
# define _LIBCPP_NO_DESTROY __attribute__((__no_destroy__))
|
||||
# if __has_cpp_attribute(_Clang::__no_destroy__)
|
||||
# define _LIBCPP_NO_DESTROY [[_Clang::__no_destroy__]]
|
||||
# else
|
||||
# define _LIBCPP_NO_DESTROY
|
||||
# endif
|
||||
|
|
@ -1149,15 +1150,6 @@ typedef __char32_t char32_t;
|
|||
# define _LIBCPP_DIAGNOSE_WARNING(...)
|
||||
# endif
|
||||
|
||||
// Use a function like macro to imply that it must be followed by a semicolon
|
||||
# if __has_cpp_attribute(fallthrough)
|
||||
# define _LIBCPP_FALLTHROUGH() [[fallthrough]]
|
||||
# elif __has_attribute(__fallthrough__)
|
||||
# define _LIBCPP_FALLTHROUGH() __attribute__((__fallthrough__))
|
||||
# else
|
||||
# define _LIBCPP_FALLTHROUGH() ((void)0)
|
||||
# endif
|
||||
|
||||
# if __has_cpp_attribute(_Clang::__lifetimebound__)
|
||||
# define _LIBCPP_LIFETIMEBOUND [[_Clang::__lifetimebound__]]
|
||||
# else
|
||||
|
|
@ -1170,8 +1162,6 @@ typedef __char32_t char32_t;
|
|||
# define _LIBCPP_NOESCAPE
|
||||
# endif
|
||||
|
||||
# define _LIBCPP_NODEBUG [[__gnu__::__nodebug__]]
|
||||
|
||||
# if __has_cpp_attribute(_Clang::__no_specializations__)
|
||||
# define _LIBCPP_NO_SPECIALIZATIONS \
|
||||
[[_Clang::__no_specializations__("Users are not allowed to specialize this standard library entity")]]
|
||||
|
|
@ -1179,43 +1169,70 @@ typedef __char32_t char32_t;
|
|||
# define _LIBCPP_NO_SPECIALIZATIONS
|
||||
# endif
|
||||
|
||||
# if __has_attribute(__standalone_debug__)
|
||||
# define _LIBCPP_STANDALONE_DEBUG __attribute__((__standalone_debug__))
|
||||
# if __has_cpp_attribute(_Clang::__standalone_debug__)
|
||||
# define _LIBCPP_STANDALONE_DEBUG [[_Clang::__standalone_debug__]]
|
||||
# else
|
||||
# define _LIBCPP_STANDALONE_DEBUG
|
||||
# endif
|
||||
|
||||
# if __has_attribute(__preferred_name__)
|
||||
# define _LIBCPP_PREFERRED_NAME(x) __attribute__((__preferred_name__(x)))
|
||||
# if __has_cpp_attribute(_Clang::__preferred_name__)
|
||||
# define _LIBCPP_PREFERRED_NAME(x) [[_Clang::__preferred_name__(x)]]
|
||||
# else
|
||||
# define _LIBCPP_PREFERRED_NAME(x)
|
||||
# endif
|
||||
|
||||
# if __has_attribute(__no_sanitize__)
|
||||
# define _LIBCPP_NO_SANITIZE(...) __attribute__((__no_sanitize__(__VA_ARGS__)))
|
||||
# if __has_cpp_attribute(_Clang::__scoped_lockable__)
|
||||
# define _LIBCPP_SCOPED_LOCKABLE [[_Clang::__scoped_lockable__]]
|
||||
# else
|
||||
# define _LIBCPP_NO_SANITIZE(...)
|
||||
# define _LIBCPP_SCOPED_LOCKABLE
|
||||
# endif
|
||||
|
||||
# if __has_attribute(__init_priority__)
|
||||
# define _LIBCPP_INIT_PRIORITY_MAX __attribute__((__init_priority__(100)))
|
||||
# if __has_cpp_attribute(_Clang::__capability__)
|
||||
# define _LIBCPP_CAPABILITY(...) [[_Clang::__capability__(__VA_ARGS__)]]
|
||||
# else
|
||||
# define _LIBCPP_INIT_PRIORITY_MAX
|
||||
# define _LIBCPP_CAPABILITY(...)
|
||||
# endif
|
||||
|
||||
# if __has_attribute(__format__)
|
||||
// The attribute uses 1-based indices for ordinary and static member functions.
|
||||
// The attribute uses 2-based indices for non-static member functions.
|
||||
# define _LIBCPP_ATTRIBUTE_FORMAT(archetype, format_string_index, first_format_arg_index) \
|
||||
__attribute__((__format__(archetype, format_string_index, first_format_arg_index)))
|
||||
# if __has_attribute(__acquire_capability__)
|
||||
# define _LIBCPP_ACQUIRE_CAPABILITY(...) __attribute__((__acquire_capability__(__VA_ARGS__)))
|
||||
# else
|
||||
# define _LIBCPP_ATTRIBUTE_FORMAT(archetype, format_string_index, first_format_arg_index) /* nothing */
|
||||
# define _LIBCPP_ACQUIRE_CAPABILITY(...)
|
||||
# endif
|
||||
|
||||
# if __has_attribute(__packed__)
|
||||
# define _LIBCPP_PACKED __attribute__((__packed__))
|
||||
# if __has_cpp_attribute(_Clang::__try_acquire_capability__)
|
||||
# define _LIBCPP_TRY_ACQUIRE_CAPABILITY(...) [[_Clang::__try_acquire_capability__(__VA_ARGS__)]]
|
||||
# else
|
||||
# define _LIBCPP_PACKED
|
||||
# define _LIBCPP_TRY_ACQUIRE_CAPABILITY(...)
|
||||
# endif
|
||||
|
||||
# if __has_cpp_attribute(_Clang::__acquire_shared_capability__)
|
||||
# define _LIBCPP_ACQUIRE_SHARED_CAPABILITY [[_Clang::__acquire_shared_capability__]]
|
||||
# else
|
||||
# define _LIBCPP_ACQUIRE_SHARED_CAPABILITY
|
||||
# endif
|
||||
|
||||
# if __has_cpp_attribute(_Clang::__try_acquire_shared_capability__)
|
||||
# define _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(...) [[_Clang::__try_acquire_shared_capability__(__VA_ARGS__)]]
|
||||
# else
|
||||
# define _LIBCPP_TRY_ACQUIRE_SHARED_CAPABILITY(...)
|
||||
# endif
|
||||
|
||||
# if __has_cpp_attribute(_Clang::__release_capability__)
|
||||
# define _LIBCPP_RELEASE_CAPABILITY [[_Clang::__release_capability__]]
|
||||
# else
|
||||
# define _LIBCPP_RELEASE_CAPABILITY
|
||||
# endif
|
||||
|
||||
# if __has_cpp_attribute(_Clang::__release_shared_capability__)
|
||||
# define _LIBCPP_RELEASE_SHARED_CAPABILITY [[_Clang::__release_shared_capability__]]
|
||||
# else
|
||||
# define _LIBCPP_RELEASE_SHARED_CAPABILITY
|
||||
# endif
|
||||
|
||||
# if __has_attribute(__requires_capability__)
|
||||
# define _LIBCPP_REQUIRES_CAPABILITY(...) __attribute__((__requires_capability__(__VA_ARGS__)))
|
||||
# else
|
||||
# define _LIBCPP_REQUIRES_CAPABILITY(...)
|
||||
# endif
|
||||
|
||||
# if defined(_LIBCPP_ABI_MICROSOFT) && __has_declspec_attribute(empty_bases)
|
||||
|
|
@ -1231,6 +1248,13 @@ typedef __char32_t char32_t;
|
|||
# define _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
|
||||
# endif
|
||||
|
||||
# if __has_feature(nullability)
|
||||
# define _LIBCPP_DIAGNOSE_NULLPTR _Nonnull
|
||||
# else
|
||||
# define _LIBCPP_DIAGNOSE_NULLPTR
|
||||
# endif
|
||||
|
||||
// TODO(LLVM 22): Remove this macro once LLVM19 support ends. __cpp_explicit_this_parameter has been set in LLVM20.
|
||||
// Clang-18 has support for deducing this, but it does not set the FTM.
|
||||
# if defined(__cpp_explicit_this_parameter) || (defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 1800)
|
||||
# define _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER 1
|
||||
|
|
|
|||
136
lib/libcxx/include/__configuration/abi.h
vendored
136
lib/libcxx/include/__configuration/abi.h
vendored
|
|
@ -38,92 +38,47 @@
|
|||
#endif
|
||||
|
||||
#if _LIBCPP_ABI_VERSION >= 2
|
||||
// Change short string representation so that string data starts at offset 0,
|
||||
// improving its alignment in some cases.
|
||||
# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
|
||||
// Fix deque iterator type in order to support incomplete types.
|
||||
# define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE
|
||||
// Fix undefined behavior in how std::list stores its linked nodes.
|
||||
# define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB
|
||||
// Fix undefined behavior in how __tree stores its end and parent nodes.
|
||||
# define _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB
|
||||
// Fix undefined behavior in how __hash_table stores its pointer types.
|
||||
# define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB
|
||||
# define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB
|
||||
# define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
|
||||
// TODO: Move the description of the remaining ABI flags to ABIGuarantees.rst or remove them.
|
||||
|
||||
// Override the default return value of exception::what() for bad_function_call::what()
|
||||
// with a string that is specific to bad_function_call (see http://wg21.link/LWG2233).
|
||||
// This is an ABI break on platforms that sign and authenticate vtable function pointers
|
||||
// because it changes the mangling of the virtual function located in the vtable, which
|
||||
// changes how it gets signed.
|
||||
# define _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE
|
||||
// Enable optimized version of __do_get_(un)signed which avoids redundant copies.
|
||||
# define _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
|
||||
// Give reverse_iterator<T> one data member of type T, not two.
|
||||
// Also, in C++17 and later, don't derive iterator types from std::iterator.
|
||||
# define _LIBCPP_ABI_NO_ITERATOR_BASES
|
||||
// Use the smallest possible integer type to represent the index of the variant.
|
||||
// Previously libc++ used "unsigned int" exclusively.
|
||||
# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION
|
||||
// Unstable attempt to provide a more optimized std::function
|
||||
# define _LIBCPP_ABI_OPTIMIZED_FUNCTION
|
||||
// All the regex constants must be distinct and nonzero.
|
||||
# define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO
|
||||
// Re-worked external template instantiations for std::string with a focus on
|
||||
// performance and fast-path inlining.
|
||||
# define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
|
||||
// Enable clang::trivial_abi on std::unique_ptr.
|
||||
# define _LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI
|
||||
// Enable clang::trivial_abi on std::shared_ptr and std::weak_ptr
|
||||
# define _LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI
|
||||
// std::random_device holds some state when it uses an implementation that gets
|
||||
// entropy from a file (see _LIBCPP_USING_DEV_RANDOM). When switching from this
|
||||
// implementation to another one on a platform that has already shipped
|
||||
// std::random_device, one needs to retain the same object layout to remain ABI
|
||||
// compatible. This switch removes these workarounds for platforms that don't care
|
||||
// about ABI compatibility.
|
||||
# define _LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT
|
||||
// Don't export the legacy __basic_string_common class and its methods from the built library.
|
||||
# define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
|
||||
// Don't export the legacy __vector_base_common class and its methods from the built library.
|
||||
# define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON
|
||||
// According to the Standard, `bitset::operator[] const` returns bool
|
||||
# define _LIBCPP_ABI_BITSET_VECTOR_BOOL_CONST_SUBSCRIPT_RETURN_BOOL
|
||||
// Fix the implementation of CityHash used for std::hash<fundamental-type>.
|
||||
// This is an ABI break because `std::hash` will return a different result,
|
||||
// which means that hashing the same object in translation units built against
|
||||
// different versions of libc++ can return inconsistent results. This is especially
|
||||
// tricky since std::hash is used in the implementation of unordered containers.
|
||||
//
|
||||
// The incorrect implementation of CityHash has the problem that it drops some
|
||||
// bits on the floor.
|
||||
# define _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION
|
||||
// Remove the base 10 implementation of std::to_chars from the dylib.
|
||||
// The implementation moved to the header, but we still export the symbols from
|
||||
// the dylib for backwards compatibility.
|
||||
|
||||
// In LLVM 20, we've changed to take these ABI breaks unconditionally. These flags only exist in case someone is running
|
||||
// into the static_asserts we added to catch the ABI break and don't care that it is one.
|
||||
// TODO(LLVM 22): Remove these flags
|
||||
# define _LIBCPP_ABI_LIST_REMOVE_NODE_POINTER_UB
|
||||
# define _LIBCPP_ABI_TREE_REMOVE_NODE_POINTER_UB
|
||||
# define _LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB
|
||||
# define _LIBCPP_ABI_FORWARD_LIST_REMOVE_NODE_POINTER_UB
|
||||
|
||||
// These flags are documented in ABIGuarantees.rst
|
||||
# define _LIBCPP_ABI_ALTERNATE_STRING_LAYOUT
|
||||
# define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON
|
||||
# define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON
|
||||
# define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10
|
||||
// Define std::array/std::string_view iterators to be __wrap_iters instead of raw
|
||||
// pointers, which prevents people from relying on a non-portable implementation
|
||||
// detail. This is especially useful because enabling bounded iterators hardening
|
||||
// requires code not to make these assumptions.
|
||||
# define _LIBCPP_ABI_ENABLE_SHARED_PTR_TRIVIAL_ABI
|
||||
# define _LIBCPP_ABI_ENABLE_UNIQUE_PTR_TRIVIAL_ABI
|
||||
# define _LIBCPP_ABI_FIX_CITYHASH_IMPLEMENTATION
|
||||
# define _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
|
||||
# define _LIBCPP_ABI_INCOMPLETE_TYPES_IN_DEQUE
|
||||
# define _LIBCPP_ABI_IOS_ALLOW_ARBITRARY_FILL_VALUE
|
||||
# define _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING
|
||||
# define _LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE
|
||||
# define _LIBCPP_ABI_NO_ITERATOR_BASES
|
||||
# define _LIBCPP_ABI_NO_RANDOM_DEVICE_COMPATIBILITY_LAYOUT
|
||||
# define _LIBCPP_ABI_OPTIMIZED_FUNCTION
|
||||
# define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO
|
||||
# define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION
|
||||
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_ARRAY
|
||||
# define _LIBCPP_ABI_USE_WRAP_ITER_IN_STD_STRING_VIEW
|
||||
// Dont' add an inline namespace for `std::filesystem`
|
||||
# define _LIBCPP_ABI_NO_FILESYSTEM_INLINE_NAMESPACE
|
||||
// std::basic_ios uses WEOF to indicate that the fill value is
|
||||
// uninitialized. However, on platforms where the size of char_type is
|
||||
// equal to or greater than the size of int_type and char_type is unsigned,
|
||||
// std::char_traits<char_type>::eq_int_type() cannot distinguish between WEOF
|
||||
// and WCHAR_MAX. This ABI setting determines whether we should instead track whether the fill
|
||||
// value has been initialized using a separate boolean, which changes the ABI.
|
||||
# define _LIBCPP_ABI_IOS_ALLOW_ARBITRARY_FILL_VALUE
|
||||
// Historically, libc++ used a type called `__compressed_pair` to reduce storage needs in cases of empty types (e.g. an
|
||||
// empty allocator in std::vector). We switched to using `[[no_unique_address]]`. However, for ABI compatibility reasons
|
||||
// we had to add artificial padding in a few places.
|
||||
//
|
||||
// This setting disables the addition of such artificial padding, leading to a more optimal
|
||||
// representation for several types.
|
||||
# define _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING
|
||||
# define _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION
|
||||
|
||||
#elif _LIBCPP_ABI_VERSION == 1
|
||||
# if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF))
|
||||
// Enable compiling copies of now inline methods into the dylib to support
|
||||
|
|
@ -138,7 +93,7 @@
|
|||
# endif
|
||||
// Feature macros for disabling pre ABI v1 features. All of these options
|
||||
// are deprecated.
|
||||
# if defined(__FreeBSD__) && __FreeBSD__ < 14
|
||||
# if defined(__FreeBSD__)
|
||||
# define _LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR
|
||||
# endif
|
||||
#endif
|
||||
|
|
@ -153,35 +108,6 @@
|
|||
// The macro below is used for all classes whose ABI have changed as part of fixing these bugs.
|
||||
#define _LIBCPP_ABI_LLVM18_NO_UNIQUE_ADDRESS __attribute__((__abi_tag__("llvm18_nua")))
|
||||
|
||||
// Changes the iterator type of select containers (see below) to a bounded iterator that keeps track of whether it's
|
||||
// within the bounds of the original container and asserts it on every dereference.
|
||||
//
|
||||
// ABI impact: changes the iterator type of the relevant containers.
|
||||
//
|
||||
// Supported containers:
|
||||
// - `span`;
|
||||
// - `string_view`.
|
||||
// #define _LIBCPP_ABI_BOUNDED_ITERATORS
|
||||
|
||||
// Changes the iterator type of `basic_string` to a bounded iterator that keeps track of whether it's within the bounds
|
||||
// of the original container and asserts it on every dereference and when performing iterator arithmetics.
|
||||
//
|
||||
// ABI impact: changes the iterator type of `basic_string` and its specializations, such as `string` and `wstring`.
|
||||
// #define _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING
|
||||
|
||||
// Changes the iterator type of `vector` to a bounded iterator that keeps track of whether it's within the bounds of the
|
||||
// original container and asserts it on every dereference and when performing iterator arithmetics. Note: this doesn't
|
||||
// yet affect `vector<bool>`.
|
||||
//
|
||||
// ABI impact: changes the iterator type of `vector` (except `vector<bool>`).
|
||||
// #define _LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR
|
||||
|
||||
// Changes the iterator type of `array` to a bounded iterator that keeps track of whether it's within the bounds of the
|
||||
// container and asserts it on every dereference and when performing iterator arithmetic.
|
||||
//
|
||||
// ABI impact: changes the iterator type of `array`, its size and its layout.
|
||||
// #define _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STD_ARRAY
|
||||
|
||||
// [[msvc::no_unique_address]] seems to mostly affect empty classes, so the padding scheme for Itanium doesn't work.
|
||||
#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING)
|
||||
# define _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING
|
||||
|
|
|
|||
|
|
@ -69,7 +69,13 @@
|
|||
|
||||
// Availability markup is disabled when building the library, or when a non-Clang
|
||||
// compiler is used because only Clang supports the necessary attributes.
|
||||
#if defined(_LIBCPP_BUILDING_LIBRARY) || defined(_LIBCXXABI_BUILDING_LIBRARY) || !defined(_LIBCPP_COMPILER_CLANG_BASED)
|
||||
//
|
||||
// We also allow users to force-disable availability markup via the `_LIBCPP_DISABLE_AVAILABILITY`
|
||||
// macro because that is the only way to work around a Clang bug related to availability
|
||||
// attributes: https://github.com/llvm/llvm-project/issues/134151.
|
||||
// Once that bug has been fixed, we should remove the macro.
|
||||
#if defined(_LIBCPP_BUILDING_LIBRARY) || defined(_LIBCXXABI_BUILDING_LIBRARY) || \
|
||||
!defined(_LIBCPP_COMPILER_CLANG_BASED) || defined(_LIBCPP_DISABLE_AVAILABILITY)
|
||||
# undef _LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS
|
||||
# define _LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS 0
|
||||
#endif
|
||||
|
|
@ -78,6 +84,9 @@
|
|||
// in all versions of the library are available.
|
||||
#if !_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS
|
||||
|
||||
# define _LIBCPP_INTRODUCED_IN_LLVM_21 1
|
||||
# define _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE /* nothing */
|
||||
|
||||
# define _LIBCPP_INTRODUCED_IN_LLVM_20 1
|
||||
# define _LIBCPP_INTRODUCED_IN_LLVM_20_ATTRIBUTE /* nothing */
|
||||
|
||||
|
|
@ -107,13 +116,15 @@
|
|||
# define _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE_PUSH /* nothing */
|
||||
# define _LIBCPP_INTRODUCED_IN_LLVM_9_ATTRIBUTE_POP /* nothing */
|
||||
|
||||
# define _LIBCPP_INTRODUCED_IN_LLVM_4 1
|
||||
# define _LIBCPP_INTRODUCED_IN_LLVM_4_ATTRIBUTE /* nothing */
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
// clang-format off
|
||||
|
||||
// LLVM 21
|
||||
// TODO: Fill this in
|
||||
# define _LIBCPP_INTRODUCED_IN_LLVM_21 0
|
||||
# define _LIBCPP_INTRODUCED_IN_LLVM_21_ATTRIBUTE __attribute__((unavailable))
|
||||
|
||||
// LLVM 20
|
||||
// TODO: Fill this in
|
||||
# define _LIBCPP_INTRODUCED_IN_LLVM_20 0
|
||||
|
|
@ -244,14 +255,6 @@
|
|||
_Pragma("clang attribute pop") \
|
||||
_Pragma("clang attribute pop")
|
||||
|
||||
// LLVM 4
|
||||
# if defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000
|
||||
# define _LIBCPP_INTRODUCED_IN_LLVM_4 0
|
||||
# else
|
||||
# define _LIBCPP_INTRODUCED_IN_LLVM_4 1
|
||||
# endif
|
||||
# define _LIBCPP_INTRODUCED_IN_LLVM_4_ATTRIBUTE __attribute__((availability(watchos, strict, introduced = 5.0)))
|
||||
|
||||
// clang-format on
|
||||
|
||||
#else
|
||||
|
|
@ -263,23 +266,6 @@
|
|||
|
||||
#endif
|
||||
|
||||
// These macros control the availability of std::bad_optional_access and
|
||||
// other exception types. These were put in the shared library to prevent
|
||||
// code bloat from every user program defining the vtable for these exception
|
||||
// types.
|
||||
//
|
||||
// Note that when exceptions are disabled, the methods that normally throw
|
||||
// these exceptions can be used even on older deployment targets, but those
|
||||
// methods will abort instead of throwing.
|
||||
#define _LIBCPP_AVAILABILITY_HAS_BAD_OPTIONAL_ACCESS _LIBCPP_INTRODUCED_IN_LLVM_4
|
||||
#define _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS _LIBCPP_INTRODUCED_IN_LLVM_4_ATTRIBUTE
|
||||
|
||||
#define _LIBCPP_AVAILABILITY_HAS_BAD_VARIANT_ACCESS _LIBCPP_INTRODUCED_IN_LLVM_4
|
||||
#define _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS _LIBCPP_INTRODUCED_IN_LLVM_4_ATTRIBUTE
|
||||
|
||||
#define _LIBCPP_AVAILABILITY_HAS_BAD_ANY_CAST _LIBCPP_INTRODUCED_IN_LLVM_4
|
||||
#define _LIBCPP_AVAILABILITY_BAD_ANY_CAST _LIBCPP_INTRODUCED_IN_LLVM_4_ATTRIBUTE
|
||||
|
||||
// These macros control the availability of all parts of <filesystem> that
|
||||
// depend on something in the dylib.
|
||||
#define _LIBCPP_AVAILABILITY_HAS_FILESYSTEM_LIBRARY _LIBCPP_INTRODUCED_IN_LLVM_9
|
||||
|
|
@ -359,18 +345,15 @@
|
|||
#define _LIBCPP_AVAILABILITY_HAS_FROM_CHARS_FLOATING_POINT _LIBCPP_INTRODUCED_IN_LLVM_20
|
||||
#define _LIBCPP_AVAILABILITY_FROM_CHARS_FLOATING_POINT _LIBCPP_INTRODUCED_IN_LLVM_20_ATTRIBUTE
|
||||
|
||||
// Define availability attributes that depend on _LIBCPP_HAS_EXCEPTIONS.
|
||||
// Those are defined in terms of the availability attributes above, and
|
||||
// should not be vendor-specific.
|
||||
#if !_LIBCPP_HAS_EXCEPTIONS
|
||||
# define _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST
|
||||
# define _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS
|
||||
# define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS
|
||||
#else
|
||||
# define _LIBCPP_AVAILABILITY_THROW_BAD_ANY_CAST _LIBCPP_AVAILABILITY_BAD_ANY_CAST
|
||||
# define _LIBCPP_AVAILABILITY_THROW_BAD_OPTIONAL_ACCESS _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
|
||||
# define _LIBCPP_AVAILABILITY_THROW_BAD_VARIANT_ACCESS _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS
|
||||
#endif
|
||||
// This controls whether `std::__hash_memory` is available in the dylib, which
|
||||
// is used for some `std::hash` specializations.
|
||||
#define _LIBCPP_AVAILABILITY_HAS_HASH_MEMORY _LIBCPP_INTRODUCED_IN_LLVM_21
|
||||
// No attribute, since we've had hash in the headers before
|
||||
|
||||
// This controls whether we provide a message for `bad_function_call::what()` that specific to `std::bad_function_call`.
|
||||
// See https://wg21.link/LWG2233. This requires `std::bad_function_call::what()` to be available in the dylib.
|
||||
#define _LIBCPP_AVAILABILITY_HAS_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE _LIBCPP_INTRODUCED_IN_LLVM_21
|
||||
// No attribute, since we've had bad_function_call::what() in the headers before
|
||||
|
||||
// Define availability attributes that depend on both
|
||||
// _LIBCPP_HAS_EXCEPTIONS and _LIBCPP_HAS_RTTI.
|
||||
|
|
|
|||
|
|
@ -33,8 +33,8 @@
|
|||
// Warn if a compiler version is used that is not supported anymore
|
||||
// LLVM RELEASE Update the minimum compiler versions
|
||||
# if defined(_LIBCPP_CLANG_VER)
|
||||
# if _LIBCPP_CLANG_VER < 1800
|
||||
# warning "Libc++ only supports Clang 18 and later"
|
||||
# if _LIBCPP_CLANG_VER < 1900
|
||||
# warning "Libc++ only supports Clang 19 and later"
|
||||
# endif
|
||||
# elif defined(_LIBCPP_APPLE_CLANG_VER)
|
||||
# if _LIBCPP_APPLE_CLANG_VER < 1500
|
||||
|
|
|
|||
|
|
@ -42,6 +42,13 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
// This is required in order for _NEWLIB_VERSION to be defined in places where we use it.
|
||||
// TODO: We shouldn't be including arbitrarily-named headers from libc++ since this can break valid
|
||||
// user code. Move code paths that need _NEWLIB_VERSION to another customization mechanism.
|
||||
#if __has_include(<picolibc.h>)
|
||||
# include <picolibc.h>
|
||||
#endif
|
||||
|
||||
#ifndef __BYTE_ORDER__
|
||||
# error \
|
||||
"Your compiler doesn't seem to define __BYTE_ORDER__, which is required by libc++ to know the endianness of your target platform"
|
||||
|
|
|
|||
|
|
@ -28,10 +28,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
|
||||
// [coroutine.handle]
|
||||
template <class _Promise = void>
|
||||
struct _LIBCPP_TEMPLATE_VIS coroutine_handle;
|
||||
struct coroutine_handle;
|
||||
|
||||
template <>
|
||||
struct _LIBCPP_TEMPLATE_VIS coroutine_handle<void> {
|
||||
struct coroutine_handle<void> {
|
||||
public:
|
||||
// [coroutine.handle.con], construct/reset
|
||||
constexpr coroutine_handle() noexcept = default;
|
||||
|
|
@ -93,7 +93,7 @@ operator<=>(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
|
|||
}
|
||||
|
||||
template <class _Promise>
|
||||
struct _LIBCPP_TEMPLATE_VIS coroutine_handle {
|
||||
struct coroutine_handle {
|
||||
public:
|
||||
// [coroutine.handle.con], construct/reset
|
||||
constexpr coroutine_handle() noexcept = default;
|
||||
|
|
@ -172,6 +172,6 @@ struct hash<coroutine_handle<_Tp>> {
|
|||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // __LIBCPP_STD_VER >= 20
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
|
||||
#endif // _LIBCPP___COROUTINE_COROUTINE_HANDLE_H
|
||||
|
|
|
|||
|
|
@ -43,6 +43,6 @@ struct coroutine_traits : public __coroutine_traits_sfinae<_Ret> {};
|
|||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // __LIBCPP_STD_VER >= 20
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
|
||||
#endif // _LIBCPP___COROUTINE_COROUTINE_TRAITS_H
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ struct noop_coroutine_promise {};
|
|||
|
||||
// [coroutine.handle.noop]
|
||||
template <>
|
||||
struct _LIBCPP_TEMPLATE_VIS coroutine_handle<noop_coroutine_promise> {
|
||||
struct coroutine_handle<noop_coroutine_promise> {
|
||||
public:
|
||||
// [coroutine.handle.noop.conv], conversion
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr operator coroutine_handle<>() const noexcept {
|
||||
|
|
@ -94,6 +94,6 @@ inline _LIBCPP_HIDE_FROM_ABI noop_coroutine_handle noop_coroutine() noexcept { r
|
|||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // __LIBCPP_STD_VER >= 20
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
|
||||
#endif // _LIBCPP___COROUTINE_NOOP_COROUTINE_HANDLE_H
|
||||
|
|
|
|||
|
|
@ -35,6 +35,6 @@ struct suspend_always {
|
|||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // __LIBCPP_STD_VER >= 20
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
|
||||
#endif // __LIBCPP___COROUTINE_TRIVIAL_AWAITABLES_H
|
||||
|
|
|
|||
4
lib/libcxx/include/__cstddef/byte.h
vendored
4
lib/libcxx/include/__cstddef/byte.h
vendored
|
|
@ -19,7 +19,7 @@
|
|||
#endif
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
namespace std { // purposefully not versioned
|
||||
_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
|
||||
|
||||
enum class byte : unsigned char {};
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ template <class _Integer, __enable_if_t<is_integral<_Integer>::value, int> = 0>
|
|||
return static_cast<_Integer>(__b);
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
|
||||
#endif // _LIBCPP_STD_VER >= 17
|
||||
|
||||
#endif // _LIBCPP___CSTDDEF_BYTE_H
|
||||
|
|
|
|||
10
lib/libcxx/include/__debug_utils/sanitizers.h
vendored
10
lib/libcxx/include/__debug_utils/sanitizers.h
vendored
|
|
@ -17,7 +17,7 @@
|
|||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
#if _LIBCPP_HAS_ASAN
|
||||
#if __has_feature(address_sanitizer)
|
||||
|
||||
extern "C" {
|
||||
_LIBCPP_EXPORTED_FROM_ABI void
|
||||
|
|
@ -28,12 +28,12 @@ _LIBCPP_EXPORTED_FROM_ABI int
|
|||
__sanitizer_verify_double_ended_contiguous_container(const void*, const void*, const void*, const void*);
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_HAS_ASAN
|
||||
#endif // __has_feature(address_sanitizer)
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
// ASan choices
|
||||
#if _LIBCPP_HAS_ASAN
|
||||
#if __has_feature(address_sanitizer)
|
||||
# define _LIBCPP_HAS_ASAN_CONTAINER_ANNOTATIONS_FOR_ALL_ALLOCATORS 1
|
||||
#endif
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ _LIBCPP_HIDE_FROM_ABI void __annotate_double_ended_contiguous_container(
|
|||
const void* __last_old_contained,
|
||||
const void* __first_new_contained,
|
||||
const void* __last_new_contained) {
|
||||
#if !_LIBCPP_HAS_ASAN
|
||||
#if !__has_feature(address_sanitizer)
|
||||
(void)__first_storage;
|
||||
(void)__last_storage;
|
||||
(void)__first_old_contained;
|
||||
|
|
@ -86,7 +86,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __annotate_contiguous_c
|
|||
const void* __last_storage,
|
||||
const void* __old_last_contained,
|
||||
const void* __new_last_contained) {
|
||||
#if !_LIBCPP_HAS_ASAN
|
||||
#if !__has_feature(address_sanitizer)
|
||||
(void)__first_storage;
|
||||
(void)__last_storage;
|
||||
(void)__old_last_contained;
|
||||
|
|
|
|||
4
lib/libcxx/include/__exception/exception.h
vendored
4
lib/libcxx/include/__exception/exception.h
vendored
|
|
@ -21,7 +21,7 @@
|
|||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace std { // purposefully not using versioning namespace
|
||||
_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
|
||||
|
||||
#if defined(_LIBCPP_ABI_VCRUNTIME) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS != 0)
|
||||
// The std::exception class was already included above, but we're explicit about this condition here for clarity.
|
||||
|
|
@ -89,6 +89,6 @@ public:
|
|||
};
|
||||
#endif // !_LIBCPP_ABI_VCRUNTIME
|
||||
|
||||
} // namespace std
|
||||
_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___EXCEPTION_EXCEPTION_H
|
||||
|
|
|
|||
68
lib/libcxx/include/__exception/exception_ptr.h
vendored
68
lib/libcxx/include/__exception/exception_ptr.h
vendored
|
|
@ -15,6 +15,7 @@
|
|||
#include <__memory/addressof.h>
|
||||
#include <__memory/construct_at.h>
|
||||
#include <__type_traits/decay.h>
|
||||
#include <__type_traits/is_pointer.h>
|
||||
#include <cstdlib>
|
||||
#include <typeinfo>
|
||||
|
||||
|
|
@ -52,7 +53,7 @@ _LIBCPP_OVERRIDABLE_FUNC_VIS __cxa_exception* __cxa_init_primary_exception(
|
|||
|
||||
#endif
|
||||
|
||||
namespace std { // purposefully not using versioning namespace
|
||||
_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
|
||||
|
||||
#ifndef _LIBCPP_ABI_MICROSOFT
|
||||
|
||||
|
|
@ -62,11 +63,13 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
|
|||
static exception_ptr __from_native_exception_pointer(void*) _NOEXCEPT;
|
||||
|
||||
template <class _Ep>
|
||||
friend _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep) _NOEXCEPT;
|
||||
friend _LIBCPP_HIDE_FROM_ABI exception_ptr __make_exception_ptr_explicit(_Ep&) _NOEXCEPT;
|
||||
|
||||
public:
|
||||
// exception_ptr is basically a COW string.
|
||||
// exception_ptr is basically a COW string so it is trivially relocatable.
|
||||
// It is also replaceable because assignment has normal value semantics.
|
||||
using __trivially_relocatable _LIBCPP_NODEBUG = exception_ptr;
|
||||
using __replaceable _LIBCPP_NODEBUG = exception_ptr;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {}
|
||||
_LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {}
|
||||
|
|
@ -89,25 +92,21 @@ public:
|
|||
friend _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr);
|
||||
};
|
||||
|
||||
template <class _Ep>
|
||||
_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
|
||||
# if _LIBCPP_HAS_EXCEPTIONS
|
||||
# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L
|
||||
# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION
|
||||
template <class _Ep>
|
||||
_LIBCPP_HIDE_FROM_ABI exception_ptr __make_exception_ptr_explicit(_Ep& __e) _NOEXCEPT {
|
||||
using _Ep2 = __decay_t<_Ep>;
|
||||
|
||||
void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep));
|
||||
# ifdef __wasm__
|
||||
// In Wasm, a destructor returns its argument
|
||||
(void)__cxxabiv1::__cxa_init_primary_exception(
|
||||
__ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) -> void* {
|
||||
# else
|
||||
(void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) {
|
||||
# endif
|
||||
auto __cleanup = [](void* __p) -> void* {
|
||||
std::__destroy_at(static_cast<_Ep2*>(__p));
|
||||
# ifdef __wasm__
|
||||
return __p;
|
||||
};
|
||||
# else
|
||||
auto __cleanup = [](void* __p) { std::__destroy_at(static_cast<_Ep2*>(__p)); };
|
||||
# endif
|
||||
});
|
||||
(void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast<std::type_info*>(&typeid(_Ep)), __cleanup);
|
||||
|
||||
try {
|
||||
::new (__ex) _Ep2(__e);
|
||||
|
|
@ -116,18 +115,47 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
|
|||
__cxxabiv1::__cxa_free_exception(__ex);
|
||||
return current_exception();
|
||||
}
|
||||
# else
|
||||
}
|
||||
# endif
|
||||
|
||||
template <class _Ep>
|
||||
_LIBCPP_HIDE_FROM_ABI exception_ptr __make_exception_ptr_via_throw(_Ep& __e) _NOEXCEPT {
|
||||
try {
|
||||
throw __e;
|
||||
} catch (...) {
|
||||
return current_exception();
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
template <class _Ep>
|
||||
_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
|
||||
// Objective-C exceptions are thrown via pointer. When throwing an Objective-C exception,
|
||||
// Clang generates a call to `objc_exception_throw` instead of the usual `__cxa_throw`.
|
||||
// That function creates an exception with a special Objective-C typeinfo instead of
|
||||
// the usual C++ typeinfo, since that is needed to implement the behavior documented
|
||||
// at [1]).
|
||||
//
|
||||
// Because of this special behavior, we can't create an exception via `__cxa_init_primary_exception`
|
||||
// for Objective-C exceptions, otherwise we'd bypass `objc_exception_throw`. See https://llvm.org/PR135089.
|
||||
//
|
||||
// [1]:
|
||||
// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Exceptions/Articles/Exceptions64Bit.html
|
||||
if _LIBCPP_CONSTEXPR (is_pointer<_Ep>::value) {
|
||||
return std::__make_exception_ptr_via_throw(__e);
|
||||
}
|
||||
|
||||
# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && !defined(_LIBCPP_CXX03_LANG)
|
||||
return std::__make_exception_ptr_explicit(__e);
|
||||
# else
|
||||
((void)__e);
|
||||
std::abort();
|
||||
return std::__make_exception_ptr_via_throw(__e);
|
||||
# endif
|
||||
}
|
||||
# else // !_LIBCPP_HAS_EXCEPTIONS
|
||||
template <class _Ep>
|
||||
_LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep) _NOEXCEPT {
|
||||
std::abort();
|
||||
}
|
||||
# endif // _LIBCPP_HAS_EXCEPTIONS
|
||||
|
||||
#else // _LIBCPP_ABI_MICROSOFT
|
||||
|
||||
|
|
@ -171,6 +199,6 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
|
|||
}
|
||||
|
||||
#endif // _LIBCPP_ABI_MICROSOFT
|
||||
} // namespace std
|
||||
_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___EXCEPTION_EXCEPTION_PTR_H
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace std { // purposefully not using versioning namespace
|
||||
_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
|
||||
|
||||
class _LIBCPP_EXPORTED_FROM_ABI nested_exception {
|
||||
exception_ptr __ptr_;
|
||||
|
|
@ -95,6 +95,6 @@ inline _LIBCPP_HIDE_FROM_ABI void rethrow_if_nested(const _Ep& __e) {
|
|||
template <class _Ep, __enable_if_t<!__can_dynamic_cast<_Ep, nested_exception>::value, int> = 0>
|
||||
inline _LIBCPP_HIDE_FROM_ABI void rethrow_if_nested(const _Ep&) {}
|
||||
|
||||
} // namespace std
|
||||
_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___EXCEPTION_NESTED_EXCEPTION_H
|
||||
|
|
|
|||
4
lib/libcxx/include/__exception/operations.h
vendored
4
lib/libcxx/include/__exception/operations.h
vendored
|
|
@ -15,7 +15,7 @@
|
|||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace std { // purposefully not using versioning namespace
|
||||
_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
|
||||
#if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) || \
|
||||
defined(_LIBCPP_BUILDING_LIBRARY)
|
||||
using unexpected_handler = void (*)();
|
||||
|
|
@ -37,6 +37,6 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr;
|
|||
|
||||
_LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT;
|
||||
[[__noreturn__]] _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr);
|
||||
} // namespace std
|
||||
_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___EXCEPTION_OPERATIONS_H
|
||||
|
|
|
|||
4
lib/libcxx/include/__exception/terminate.h
vendored
4
lib/libcxx/include/__exception/terminate.h
vendored
|
|
@ -15,8 +15,8 @@
|
|||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
namespace std { // purposefully not using versioning namespace
|
||||
_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
|
||||
[[__noreturn__]] _LIBCPP_EXPORTED_FROM_ABI void terminate() _NOEXCEPT;
|
||||
} // namespace std
|
||||
_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP___EXCEPTION_TERMINATE_H
|
||||
|
|
|
|||
45
lib/libcxx/include/__expected/expected.h
vendored
45
lib/libcxx/include/__expected/expected.h
vendored
|
|
@ -25,10 +25,12 @@
|
|||
#include <__type_traits/is_assignable.h>
|
||||
#include <__type_traits/is_constructible.h>
|
||||
#include <__type_traits/is_convertible.h>
|
||||
#include <__type_traits/is_core_convertible.h>
|
||||
#include <__type_traits/is_function.h>
|
||||
#include <__type_traits/is_nothrow_assignable.h>
|
||||
#include <__type_traits/is_nothrow_constructible.h>
|
||||
#include <__type_traits/is_reference.h>
|
||||
#include <__type_traits/is_replaceable.h>
|
||||
#include <__type_traits/is_same.h>
|
||||
#include <__type_traits/is_swappable.h>
|
||||
#include <__type_traits/is_trivially_constructible.h>
|
||||
|
|
@ -470,6 +472,8 @@ public:
|
|||
__conditional_t<__libcpp_is_trivially_relocatable<_Tp>::value && __libcpp_is_trivially_relocatable<_Err>::value,
|
||||
expected,
|
||||
void>;
|
||||
using __replaceable _LIBCPP_NODEBUG =
|
||||
__conditional_t<__is_replaceable_v<_Tp> && __is_replaceable_v<_Err>, expected, void>;
|
||||
|
||||
template <class _Up>
|
||||
using rebind = expected<_Up, error_type>;
|
||||
|
|
@ -1139,8 +1143,15 @@ public:
|
|||
|
||||
// [expected.object.eq], equality operators
|
||||
template <class _T2, class _E2>
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y)
|
||||
requires(!is_void_v<_T2>)
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) {
|
||||
# if _LIBCPP_STD_VER >= 26
|
||||
&& requires {
|
||||
{ *__x == *__y } -> __core_convertible_to<bool>;
|
||||
{ __x.error() == __y.error() } -> __core_convertible_to<bool>;
|
||||
}
|
||||
# endif
|
||||
{
|
||||
if (__x.__has_val() != __y.__has_val()) {
|
||||
return false;
|
||||
} else {
|
||||
|
|
@ -1153,12 +1164,24 @@ public:
|
|||
}
|
||||
|
||||
template <class _T2>
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v) {
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const _T2& __v)
|
||||
# if _LIBCPP_STD_VER >= 26
|
||||
requires(!__is_std_expected<_T2>::value) && requires {
|
||||
{ *__x == __v } -> __core_convertible_to<bool>;
|
||||
}
|
||||
# endif
|
||||
{
|
||||
return __x.__has_val() && static_cast<bool>(__x.__val() == __v);
|
||||
}
|
||||
|
||||
template <class _E2>
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e) {
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __e)
|
||||
# if _LIBCPP_STD_VER >= 26
|
||||
requires requires {
|
||||
{ __x.error() == __e.error() } -> __core_convertible_to<bool>;
|
||||
}
|
||||
# endif
|
||||
{
|
||||
return !__x.__has_val() && static_cast<bool>(__x.__unex() == __e.error());
|
||||
}
|
||||
};
|
||||
|
|
@ -1851,7 +1874,13 @@ public:
|
|||
// [expected.void.eq], equality operators
|
||||
template <class _T2, class _E2>
|
||||
requires is_void_v<_T2>
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y) {
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const expected<_T2, _E2>& __y)
|
||||
# if _LIBCPP_STD_VER >= 26
|
||||
requires requires {
|
||||
{ __x.error() == __y.error() } -> __core_convertible_to<bool>;
|
||||
}
|
||||
# endif
|
||||
{
|
||||
if (__x.__has_val() != __y.__has_val()) {
|
||||
return false;
|
||||
} else {
|
||||
|
|
@ -1860,7 +1889,13 @@ public:
|
|||
}
|
||||
|
||||
template <class _E2>
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y) {
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const expected& __x, const unexpected<_E2>& __y)
|
||||
# if _LIBCPP_STD_VER >= 26
|
||||
requires requires {
|
||||
{ __x.error() == __y.error() } -> __core_convertible_to<bool>;
|
||||
}
|
||||
# endif
|
||||
{
|
||||
return !__x.__has_val() && static_cast<bool>(__x.__unex() == __y.error());
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ private:
|
|||
return;
|
||||
}
|
||||
if (__ec && (!__allow_dne || !__is_dne_error(__ec)))
|
||||
__throw_filesystem_error(__msg, __p_, __ec);
|
||||
filesystem::__throw_filesystem_error(__msg, __p_, __ec);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI void __refresh(error_code* __ec = nullptr) {
|
||||
|
|
|
|||
6
lib/libcxx/include/__filesystem/operations.h
vendored
6
lib/libcxx/include/__filesystem/operations.h
vendored
|
|
@ -66,6 +66,9 @@ _LIBCPP_EXPORTED_FROM_ABI bool __remove(const path&, error_code* __ec = nullptr)
|
|||
_LIBCPP_EXPORTED_FROM_ABI void __rename(const path& __from, const path& __to, error_code* __ec = nullptr);
|
||||
_LIBCPP_EXPORTED_FROM_ABI void __resize_file(const path&, uintmax_t __size, error_code* = nullptr);
|
||||
_LIBCPP_EXPORTED_FROM_ABI path __temp_directory_path(error_code* __ec = nullptr);
|
||||
_LIBCPP_EXPORTED_FROM_ABI bool __fs_is_empty(const path& __p, error_code* __ec = nullptr);
|
||||
_LIBCPP_EXPORTED_FROM_ABI void __permissions(const path&, perms, perm_options, error_code* = nullptr);
|
||||
_LIBCPP_EXPORTED_FROM_ABI space_info __space(const path&, error_code* __ec = nullptr);
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI path absolute(const path& __p) { return __absolute(__p); }
|
||||
inline _LIBCPP_HIDE_FROM_ABI path absolute(const path& __p, error_code& __ec) { return __absolute(__p, &__ec); }
|
||||
|
|
@ -182,7 +185,6 @@ inline _LIBCPP_HIDE_FROM_ABI bool is_directory(const path& __p) { return is_dire
|
|||
inline _LIBCPP_HIDE_FROM_ABI bool is_directory(const path& __p, error_code& __ec) noexcept {
|
||||
return is_directory(__status(__p, &__ec));
|
||||
}
|
||||
_LIBCPP_EXPORTED_FROM_ABI bool __fs_is_empty(const path& __p, error_code* __ec = nullptr);
|
||||
inline _LIBCPP_HIDE_FROM_ABI bool is_empty(const path& __p) { return __fs_is_empty(__p); }
|
||||
inline _LIBCPP_HIDE_FROM_ABI bool is_empty(const path& __p, error_code& __ec) { return __fs_is_empty(__p, &__ec); }
|
||||
inline _LIBCPP_HIDE_FROM_ABI bool is_fifo(file_status __s) noexcept { return __s.type() == file_type::fifo; }
|
||||
|
|
@ -220,7 +222,6 @@ inline _LIBCPP_HIDE_FROM_ABI void last_write_time(const path& __p, file_time_typ
|
|||
inline _LIBCPP_HIDE_FROM_ABI void last_write_time(const path& __p, file_time_type __t, error_code& __ec) noexcept {
|
||||
__last_write_time(__p, __t, &__ec);
|
||||
}
|
||||
_LIBCPP_EXPORTED_FROM_ABI void __permissions(const path&, perms, perm_options, error_code* = nullptr);
|
||||
inline _LIBCPP_HIDE_FROM_ABI void
|
||||
permissions(const path& __p, perms __prms, perm_options __opts = perm_options::replace) {
|
||||
__permissions(__p, __prms, __opts);
|
||||
|
|
@ -281,7 +282,6 @@ inline _LIBCPP_HIDE_FROM_ABI void resize_file(const path& __p, uintmax_t __ns) {
|
|||
inline _LIBCPP_HIDE_FROM_ABI void resize_file(const path& __p, uintmax_t __ns, error_code& __ec) noexcept {
|
||||
return __resize_file(__p, __ns, &__ec);
|
||||
}
|
||||
_LIBCPP_EXPORTED_FROM_ABI space_info __space(const path&, error_code* __ec = nullptr);
|
||||
inline _LIBCPP_HIDE_FROM_ABI space_info space(const path& __p) { return __space(__p); }
|
||||
inline _LIBCPP_HIDE_FROM_ABI space_info space(const path& __p, error_code& __ec) noexcept {
|
||||
return __space(__p, &__ec);
|
||||
|
|
|
|||
5
lib/libcxx/include/__filesystem/path.h
vendored
5
lib/libcxx/include/__filesystem/path.h
vendored
|
|
@ -17,7 +17,9 @@
|
|||
#include <__fwd/functional.h>
|
||||
#include <__iterator/back_insert_iterator.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__memory/addressof.h>
|
||||
#include <__type_traits/decay.h>
|
||||
#include <__type_traits/enable_if.h>
|
||||
#include <__type_traits/is_pointer.h>
|
||||
#include <__type_traits/remove_const.h>
|
||||
#include <__type_traits/remove_pointer.h>
|
||||
|
|
@ -27,7 +29,6 @@
|
|||
|
||||
#if _LIBCPP_HAS_LOCALIZATION
|
||||
# include <iomanip> // for quoted
|
||||
# include <locale>
|
||||
#endif
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
|
|
@ -583,7 +584,7 @@ public:
|
|||
|
||||
template <class _ECharT, __enable_if_t<__can_convert_char<_ECharT>::value, int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI path& operator+=(_ECharT __x) {
|
||||
_PathCVT<_ECharT>::__append_source(__pn_, basic_string_view<_ECharT>(&__x, 1));
|
||||
_PathCVT<_ECharT>::__append_source(__pn_, basic_string_view<_ECharT>(std::addressof(__x), 1));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
|||
7
lib/libcxx/include/__filesystem/u8path.h
vendored
7
lib/libcxx/include/__filesystem/u8path.h
vendored
|
|
@ -13,14 +13,9 @@
|
|||
#include <__algorithm/unwrap_iter.h>
|
||||
#include <__config>
|
||||
#include <__filesystem/path.h>
|
||||
#include <__locale>
|
||||
#include <string>
|
||||
|
||||
// Only required on Windows for __widen_from_utf8, and included conservatively
|
||||
// because it requires support for localization.
|
||||
#if defined(_LIBCPP_WIN32API)
|
||||
# include <locale>
|
||||
#endif
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
|
|
|||
423
lib/libcxx/include/__flat_map/flat_map.h
vendored
423
lib/libcxx/include/__flat_map/flat_map.h
vendored
File diff suppressed because it is too large
Load diff
27
lib/libcxx/include/__flat_map/flat_multimap.h
vendored
27
lib/libcxx/include/__flat_map/flat_multimap.h
vendored
|
|
@ -10,18 +10,16 @@
|
|||
#ifndef _LIBCPP___FLAT_MAP_FLAT_MULTIMAP_H
|
||||
#define _LIBCPP___FLAT_MAP_FLAT_MULTIMAP_H
|
||||
|
||||
#include <__algorithm/equal_range.h>
|
||||
#include <__algorithm/lexicographical_compare_three_way.h>
|
||||
#include <__algorithm/lower_bound.h>
|
||||
#include <__algorithm/min.h>
|
||||
#include <__algorithm/ranges_equal.h>
|
||||
#include <__algorithm/ranges_equal_range.h>
|
||||
#include <__algorithm/ranges_inplace_merge.h>
|
||||
#include <__algorithm/ranges_is_sorted.h>
|
||||
#include <__algorithm/ranges_lower_bound.h>
|
||||
#include <__algorithm/ranges_partition_point.h>
|
||||
#include <__algorithm/ranges_sort.h>
|
||||
#include <__algorithm/ranges_unique.h>
|
||||
#include <__algorithm/ranges_upper_bound.h>
|
||||
#include <__algorithm/remove_if.h>
|
||||
#include <__algorithm/upper_bound.h>
|
||||
#include <__assert>
|
||||
#include <__compare/synth_three_way.h>
|
||||
#include <__concepts/convertible_to.h>
|
||||
|
|
@ -443,7 +441,7 @@ public:
|
|||
is_move_constructible_v<mapped_type>
|
||||
_LIBCPP_HIDE_FROM_ABI iterator emplace(_Args&&... __args) {
|
||||
std::pair<key_type, mapped_type> __pair(std::forward<_Args>(__args)...);
|
||||
auto __key_it = ranges::upper_bound(__containers_.keys, __pair.first, __compare_);
|
||||
auto __key_it = std::upper_bound(__containers_.keys.begin(), __containers_.keys.end(), __pair.first, __compare_);
|
||||
auto __mapped_it = __corresponding_mapped_it(*this, __key_it);
|
||||
|
||||
return __flat_map_utils::__emplace_exact_pos(
|
||||
|
|
@ -473,7 +471,7 @@ public:
|
|||
// |
|
||||
// hint
|
||||
// We want to insert "2" after the last existing "2"
|
||||
__key_iter = ranges::upper_bound(__containers_.keys.begin(), __key_iter, __pair.first, __compare_);
|
||||
__key_iter = std::upper_bound(__containers_.keys.begin(), __key_iter, __pair.first, __compare_);
|
||||
__mapped_iter = __corresponding_mapped_it(*this, __key_iter);
|
||||
} else {
|
||||
_LIBCPP_ASSERT_INTERNAL(!__prev_larger && __next_smaller, "this means that the multimap is not sorted");
|
||||
|
|
@ -485,7 +483,7 @@ public:
|
|||
// |
|
||||
// hint
|
||||
// We want to insert "2" before the first existing "2"
|
||||
__key_iter = ranges::lower_bound(__key_iter, __containers_.keys.end(), __pair.first, __compare_);
|
||||
__key_iter = std::lower_bound(__key_iter, __containers_.keys.end(), __pair.first, __compare_);
|
||||
__mapped_iter = __corresponding_mapped_it(*this, __key_iter);
|
||||
}
|
||||
return __flat_map_utils::__emplace_exact_pos(
|
||||
|
|
@ -804,7 +802,8 @@ private:
|
|||
|
||||
template <class _Self, class _Kp>
|
||||
_LIBCPP_HIDE_FROM_ABI static auto __equal_range_impl(_Self&& __self, const _Kp& __key) {
|
||||
auto [__key_first, __key_last] = ranges::equal_range(__self.__containers_.keys, __key, __self.__compare_);
|
||||
auto [__key_first, __key_last] =
|
||||
std::equal_range(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __key, __self.__compare_);
|
||||
|
||||
using __iterator_type = ranges::iterator_t<decltype(__self)>;
|
||||
return std::make_pair(__iterator_type(__key_first, __corresponding_mapped_it(__self, __key_first)),
|
||||
|
|
@ -813,24 +812,26 @@ private:
|
|||
|
||||
template <class _Res, class _Self, class _Kp>
|
||||
_LIBCPP_HIDE_FROM_ABI static _Res __lower_bound(_Self&& __self, _Kp& __x) {
|
||||
auto __key_iter = ranges::lower_bound(__self.__containers_.keys, __x, __self.__compare_);
|
||||
auto __key_iter =
|
||||
std::lower_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __x, __self.__compare_);
|
||||
auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter);
|
||||
return _Res(std::move(__key_iter), std::move(__mapped_iter));
|
||||
}
|
||||
|
||||
template <class _Res, class _Self, class _Kp>
|
||||
_LIBCPP_HIDE_FROM_ABI static _Res __upper_bound(_Self&& __self, _Kp& __x) {
|
||||
auto __key_iter = ranges::upper_bound(__self.__containers_.keys, __x, __self.__compare_);
|
||||
auto __key_iter =
|
||||
std::upper_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __x, __self.__compare_);
|
||||
auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter);
|
||||
return _Res(std::move(__key_iter), std::move(__mapped_iter));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) {
|
||||
if constexpr (requires { __containers_.keys.reserve(__size); }) {
|
||||
if constexpr (__container_traits<_KeyContainer>::__reservable) {
|
||||
__containers_.keys.reserve(__size);
|
||||
}
|
||||
|
||||
if constexpr (requires { __containers_.values.reserve(__size); }) {
|
||||
if constexpr (__container_traits<_MappedContainer>::__reservable) {
|
||||
__containers_.values.reserve(__size);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,12 @@
|
|||
#include <__compare/three_way_comparable.h>
|
||||
#include <__concepts/convertible_to.h>
|
||||
#include <__config>
|
||||
#include <__cstddef/size_t.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__iterator/product_iterator.h>
|
||||
#include <__memory/addressof.h>
|
||||
#include <__type_traits/conditional.h>
|
||||
#include <__utility/forward.h>
|
||||
#include <__utility/move.h>
|
||||
#include <__utility/pair.h>
|
||||
|
||||
|
|
@ -46,7 +49,7 @@ private:
|
|||
|
||||
struct __arrow_proxy {
|
||||
__reference __ref_;
|
||||
_LIBCPP_HIDE_FROM_ABI __reference* operator->() { return std::addressof(__ref_); }
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __reference* operator->() { return std::addressof(__ref_); }
|
||||
};
|
||||
|
||||
__key_iterator __key_iter_;
|
||||
|
|
@ -57,6 +60,8 @@ private:
|
|||
template <class, class, class, bool>
|
||||
friend struct __key_value_iterator;
|
||||
|
||||
friend struct __product_iterator_traits<__key_value_iterator>;
|
||||
|
||||
public:
|
||||
using iterator_concept = random_access_iterator_tag;
|
||||
// `__key_value_iterator` only satisfy "Cpp17InputIterator" named requirements, because
|
||||
|
|
@ -69,104 +74,141 @@ public:
|
|||
|
||||
_LIBCPP_HIDE_FROM_ABI __key_value_iterator() = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __key_value_iterator(__key_value_iterator<_Owner, _KeyContainer, _MappedContainer, !_Const> __i)
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
__key_value_iterator(__key_value_iterator<_Owner, _KeyContainer, _MappedContainer, !_Const> __i)
|
||||
requires _Const && convertible_to<typename _KeyContainer::iterator, __key_iterator> &&
|
||||
convertible_to<typename _MappedContainer::iterator, __mapped_iterator>
|
||||
: __key_iter_(std::move(__i.__key_iter_)), __mapped_iter_(std::move(__i.__mapped_iter_)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __key_value_iterator(__key_iterator __key_iter, __mapped_iterator __mapped_iter)
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
__key_value_iterator(__key_iterator __key_iter, __mapped_iterator __mapped_iter)
|
||||
: __key_iter_(std::move(__key_iter)), __mapped_iter_(std::move(__mapped_iter)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __reference operator*() const { return __reference(*__key_iter_, *__mapped_iter_); }
|
||||
_LIBCPP_HIDE_FROM_ABI __arrow_proxy operator->() const { return __arrow_proxy{**this}; }
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __reference operator*() const {
|
||||
return __reference(*__key_iter_, *__mapped_iter_);
|
||||
}
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __arrow_proxy operator->() const { return __arrow_proxy{**this}; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator++() {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator& operator++() {
|
||||
++__key_iter_;
|
||||
++__mapped_iter_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __key_value_iterator operator++(int) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator operator++(int) {
|
||||
__key_value_iterator __tmp(*this);
|
||||
++*this;
|
||||
return __tmp;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator--() {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator& operator--() {
|
||||
--__key_iter_;
|
||||
--__mapped_iter_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __key_value_iterator operator--(int) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator operator--(int) {
|
||||
__key_value_iterator __tmp(*this);
|
||||
--*this;
|
||||
return __tmp;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator+=(difference_type __x) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator& operator+=(difference_type __x) {
|
||||
__key_iter_ += __x;
|
||||
__mapped_iter_ += __x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator-=(difference_type __x) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator& operator-=(difference_type __x) {
|
||||
__key_iter_ -= __x;
|
||||
__mapped_iter_ -= __x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __reference operator[](difference_type __n) const { return *(*this + __n); }
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __reference operator[](difference_type __n) const {
|
||||
return *(*this + __n);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool
|
||||
operator==(const __key_value_iterator& __x, const __key_value_iterator& __y) {
|
||||
return __x.__key_iter_ == __y.__key_iter_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend bool operator<(const __key_value_iterator& __x, const __key_value_iterator& __y) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool
|
||||
operator<(const __key_value_iterator& __x, const __key_value_iterator& __y) {
|
||||
return __x.__key_iter_ < __y.__key_iter_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend bool operator>(const __key_value_iterator& __x, const __key_value_iterator& __y) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool
|
||||
operator>(const __key_value_iterator& __x, const __key_value_iterator& __y) {
|
||||
return __y < __x;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend bool operator<=(const __key_value_iterator& __x, const __key_value_iterator& __y) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool
|
||||
operator<=(const __key_value_iterator& __x, const __key_value_iterator& __y) {
|
||||
return !(__y < __x);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend bool operator>=(const __key_value_iterator& __x, const __key_value_iterator& __y) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool
|
||||
operator>=(const __key_value_iterator& __x, const __key_value_iterator& __y) {
|
||||
return !(__x < __y);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend auto operator<=>(const __key_value_iterator& __x, const __key_value_iterator& __y)
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend auto
|
||||
operator<=>(const __key_value_iterator& __x, const __key_value_iterator& __y)
|
||||
requires three_way_comparable<__key_iterator>
|
||||
{
|
||||
return __x.__key_iter_ <=> __y.__key_iter_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator+(const __key_value_iterator& __i, difference_type __n) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend __key_value_iterator
|
||||
operator+(const __key_value_iterator& __i, difference_type __n) {
|
||||
auto __tmp = __i;
|
||||
__tmp += __n;
|
||||
return __tmp;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator+(difference_type __n, const __key_value_iterator& __i) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend __key_value_iterator
|
||||
operator+(difference_type __n, const __key_value_iterator& __i) {
|
||||
return __i + __n;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator-(const __key_value_iterator& __i, difference_type __n) {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend __key_value_iterator
|
||||
operator-(const __key_value_iterator& __i, difference_type __n) {
|
||||
auto __tmp = __i;
|
||||
__tmp -= __n;
|
||||
return __tmp;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend difference_type
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend difference_type
|
||||
operator-(const __key_value_iterator& __x, const __key_value_iterator& __y) {
|
||||
return difference_type(__x.__key_iter_ - __y.__key_iter_);
|
||||
}
|
||||
};
|
||||
|
||||
template <class _Owner, class _KeyContainer, class _MappedContainer, bool _Const>
|
||||
struct __product_iterator_traits<__key_value_iterator<_Owner, _KeyContainer, _MappedContainer, _Const>> {
|
||||
static constexpr size_t __size = 2;
|
||||
|
||||
template <size_t _Nth, class _Iter>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static decltype(auto) __get_iterator_element(_Iter&& __it)
|
||||
requires(_Nth <= 1)
|
||||
{
|
||||
if constexpr (_Nth == 0) {
|
||||
return std::forward<_Iter>(__it).__key_iter_;
|
||||
} else {
|
||||
return std::forward<_Iter>(__it).__mapped_iter_;
|
||||
}
|
||||
}
|
||||
|
||||
template <class _KeyIter, class _MappedIter>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto
|
||||
__make_product_iterator(_KeyIter&& __key_iter, _MappedIter&& __mapped_iter) {
|
||||
return __key_value_iterator<_Owner, _KeyContainer, _MappedContainer, _Const>(
|
||||
std::forward<_KeyIter>(__key_iter), std::forward<_MappedIter>(__mapped_iter));
|
||||
}
|
||||
};
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
|
|
|
|||
26
lib/libcxx/include/__flat_map/utils.h
vendored
26
lib/libcxx/include/__flat_map/utils.h
vendored
|
|
@ -11,6 +11,7 @@
|
|||
#define _LIBCPP___FLAT_MAP_UTILS_H
|
||||
|
||||
#include <__config>
|
||||
#include <__iterator/product_iterator.h>
|
||||
#include <__type_traits/container_traits.h>
|
||||
#include <__utility/exception_guard.h>
|
||||
#include <__utility/forward.h>
|
||||
|
|
@ -35,7 +36,7 @@ struct __flat_map_utils {
|
|||
// roll back the changes it made to the map. If it cannot roll back the changes, it will
|
||||
// clear the map.
|
||||
template <class _Map, class _IterK, class _IterM, class _KeyArg, class... _MArgs>
|
||||
_LIBCPP_HIDE_FROM_ABI static typename _Map::iterator __emplace_exact_pos(
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static typename _Map::iterator __emplace_exact_pos(
|
||||
_Map& __map, _IterK&& __it_key, _IterM&& __it_mapped, _KeyArg&& __key, _MArgs&&... __mapped_args) {
|
||||
auto __on_key_failed = std::__make_exception_guard([&]() noexcept {
|
||||
using _KeyContainer = typename _Map::key_container_type;
|
||||
|
|
@ -79,10 +80,8 @@ struct __flat_map_utils {
|
|||
return typename _Map::iterator(std::move(__key_it), std::move(__mapped_it));
|
||||
}
|
||||
|
||||
// TODO: We could optimize this, see
|
||||
// https://github.com/llvm/llvm-project/issues/108624
|
||||
template <class _Map, class _InputIterator, class _Sentinel>
|
||||
_LIBCPP_HIDE_FROM_ABI static typename _Map::size_type
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static typename _Map::size_type
|
||||
__append(_Map& __map, _InputIterator __first, _Sentinel __last) {
|
||||
typename _Map::size_type __num_appended = 0;
|
||||
for (; __first != __last; ++__first) {
|
||||
|
|
@ -93,6 +92,25 @@ struct __flat_map_utils {
|
|||
}
|
||||
return __num_appended;
|
||||
}
|
||||
|
||||
template <class _Map, class _InputIterator>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static typename _Map::size_type
|
||||
__append(_Map& __map, _InputIterator __first, _InputIterator __last)
|
||||
requires __is_product_iterator_of_size<_InputIterator, 2>::value
|
||||
{
|
||||
auto __s1 = __map.__containers_.keys.size();
|
||||
__map.__containers_.keys.insert(
|
||||
__map.__containers_.keys.end(),
|
||||
__product_iterator_traits<_InputIterator>::template __get_iterator_element<0>(__first),
|
||||
__product_iterator_traits<_InputIterator>::template __get_iterator_element<0>(__last));
|
||||
|
||||
__map.__containers_.values.insert(
|
||||
__map.__containers_.values.end(),
|
||||
__product_iterator_traits<_InputIterator>::template __get_iterator_element<1>(__first),
|
||||
__product_iterator_traits<_InputIterator>::template __get_iterator_element<1>(__last));
|
||||
|
||||
return __map.__containers_.keys.size() - __s1;
|
||||
}
|
||||
};
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
|
|
|
|||
792
lib/libcxx/include/__flat_set/flat_multiset.h
vendored
Normal file
792
lib/libcxx/include/__flat_set/flat_multiset.h
vendored
Normal file
|
|
@ -0,0 +1,792 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___FLAT_MAP_FLAT_MULTISET_H
|
||||
#define _LIBCPP___FLAT_MAP_FLAT_MULTISET_H
|
||||
|
||||
#include <__algorithm/equal_range.h>
|
||||
#include <__algorithm/lexicographical_compare_three_way.h>
|
||||
#include <__algorithm/lower_bound.h>
|
||||
#include <__algorithm/min.h>
|
||||
#include <__algorithm/ranges_equal.h>
|
||||
#include <__algorithm/ranges_inplace_merge.h>
|
||||
#include <__algorithm/ranges_is_sorted.h>
|
||||
#include <__algorithm/ranges_sort.h>
|
||||
#include <__algorithm/ranges_unique.h>
|
||||
#include <__algorithm/remove_if.h>
|
||||
#include <__algorithm/upper_bound.h>
|
||||
#include <__assert>
|
||||
#include <__compare/synth_three_way.h>
|
||||
#include <__concepts/convertible_to.h>
|
||||
#include <__concepts/swappable.h>
|
||||
#include <__config>
|
||||
#include <__cstddef/byte.h>
|
||||
#include <__cstddef/ptrdiff_t.h>
|
||||
#include <__flat_map/key_value_iterator.h>
|
||||
#include <__flat_map/sorted_equivalent.h>
|
||||
#include <__flat_set/ra_iterator.h>
|
||||
#include <__flat_set/utils.h>
|
||||
#include <__functional/invoke.h>
|
||||
#include <__functional/is_transparent.h>
|
||||
#include <__functional/operations.h>
|
||||
#include <__fwd/vector.h>
|
||||
#include <__iterator/concepts.h>
|
||||
#include <__iterator/distance.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__iterator/prev.h>
|
||||
#include <__iterator/ranges_iterator_traits.h>
|
||||
#include <__iterator/reverse_iterator.h>
|
||||
#include <__memory/allocator_traits.h>
|
||||
#include <__memory/uses_allocator.h>
|
||||
#include <__memory/uses_allocator_construction.h>
|
||||
#include <__ranges/access.h>
|
||||
#include <__ranges/concepts.h>
|
||||
#include <__ranges/container_compatible_range.h>
|
||||
#include <__ranges/drop_view.h>
|
||||
#include <__ranges/from_range.h>
|
||||
#include <__ranges/ref_view.h>
|
||||
#include <__ranges/size.h>
|
||||
#include <__ranges/subrange.h>
|
||||
#include <__ranges/zip_view.h>
|
||||
#include <__type_traits/conjunction.h>
|
||||
#include <__type_traits/container_traits.h>
|
||||
#include <__type_traits/invoke.h>
|
||||
#include <__type_traits/is_allocator.h>
|
||||
#include <__type_traits/is_nothrow_constructible.h>
|
||||
#include <__type_traits/is_same.h>
|
||||
#include <__type_traits/maybe_const.h>
|
||||
#include <__utility/as_const.h>
|
||||
#include <__utility/exception_guard.h>
|
||||
#include <__utility/move.h>
|
||||
#include <__utility/pair.h>
|
||||
#include <__utility/scope_guard.h>
|
||||
#include <__vector/vector.h>
|
||||
#include <initializer_list>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class _Key, class _Compare = less<_Key>, class _KeyContainer = vector<_Key>>
|
||||
class flat_multiset {
|
||||
template <class, class, class>
|
||||
friend class flat_multiset;
|
||||
|
||||
friend __flat_set_utils;
|
||||
|
||||
static_assert(is_same_v<_Key, typename _KeyContainer::value_type>);
|
||||
static_assert(!is_same_v<_KeyContainer, std::vector<bool>>, "vector<bool> is not a sequence container");
|
||||
|
||||
public:
|
||||
// types
|
||||
using key_type = _Key;
|
||||
using value_type = _Key;
|
||||
using key_compare = __type_identity_t<_Compare>;
|
||||
using value_compare = _Compare;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using size_type = typename _KeyContainer::size_type;
|
||||
using difference_type = typename _KeyContainer::difference_type;
|
||||
using iterator = __ra_iterator<flat_multiset, typename _KeyContainer::const_iterator>;
|
||||
using const_iterator = iterator;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
using container_type = _KeyContainer;
|
||||
|
||||
public:
|
||||
// [flat.multiset.cons], constructors
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset() noexcept(is_nothrow_default_constructible_v<_KeyContainer> &&
|
||||
is_nothrow_default_constructible_v<_Compare>)
|
||||
: __keys_(), __compare_() {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(const flat_multiset&) = default;
|
||||
|
||||
// The copy/move constructors are not specified in the spec, which means they should be defaulted.
|
||||
// However, the move constructor can potentially leave a moved-from object in an inconsistent
|
||||
// state if an exception is thrown.
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(flat_multiset&& __other) noexcept(
|
||||
is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_Compare>)
|
||||
# if _LIBCPP_HAS_EXCEPTIONS
|
||||
try
|
||||
# endif // _LIBCPP_HAS_EXCEPTIONS
|
||||
: __keys_(std::move(__other.__keys_)), __compare_(std::move(__other.__compare_)) {
|
||||
__other.clear();
|
||||
# if _LIBCPP_HAS_EXCEPTIONS
|
||||
} catch (...) {
|
||||
__other.clear();
|
||||
// gcc does not like the `throw` keyword in a conditionally noexcept function
|
||||
if constexpr (!(is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_Compare>)) {
|
||||
throw;
|
||||
}
|
||||
# endif // _LIBCPP_HAS_EXCEPTIONS
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI explicit flat_multiset(const key_compare& __comp) : __keys_(), __compare_(__comp) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI explicit flat_multiset(container_type __keys, const key_compare& __comp = key_compare())
|
||||
: __keys_(std::move(__keys)), __compare_(__comp) {
|
||||
ranges::sort(__keys_, __compare_);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
flat_multiset(sorted_equivalent_t, container_type __keys, const key_compare& __comp = key_compare())
|
||||
: __keys_(std::move(__keys)), __compare_(__comp) {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");
|
||||
}
|
||||
|
||||
template <class _InputIterator>
|
||||
requires __has_input_iterator_category<_InputIterator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
flat_multiset(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare())
|
||||
: __keys_(), __compare_(__comp) {
|
||||
insert(__first, __last);
|
||||
}
|
||||
|
||||
template <class _InputIterator>
|
||||
requires __has_input_iterator_category<_InputIterator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(
|
||||
sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare())
|
||||
: __keys_(__first, __last), __compare_(__comp) {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");
|
||||
}
|
||||
|
||||
template <_ContainerCompatibleRange<value_type> _Range>
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t __fr, _Range&& __rg)
|
||||
: flat_multiset(__fr, std::forward<_Range>(__rg), key_compare()) {}
|
||||
|
||||
template <_ContainerCompatibleRange<value_type> _Range>
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const key_compare& __comp) : flat_multiset(__comp) {
|
||||
insert_range(std::forward<_Range>(__rg));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(initializer_list<value_type> __il, const key_compare& __comp = key_compare())
|
||||
: flat_multiset(__il.begin(), __il.end(), __comp) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
flat_multiset(sorted_equivalent_t, initializer_list<value_type> __il, const key_compare& __comp = key_compare())
|
||||
: flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __comp) {}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI explicit flat_multiset(const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() {}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(const key_compare& __comp, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) {}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(const container_type& __keys, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_() {
|
||||
ranges::sort(__keys_, __compare_);
|
||||
}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
flat_multiset(const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_(__comp) {
|
||||
ranges::sort(__keys_, __compare_);
|
||||
}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(sorted_equivalent_t, const container_type& __keys, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_() {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");
|
||||
}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
flat_multiset(sorted_equivalent_t, const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_(__comp) {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");
|
||||
}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(const flat_multiset& __other, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __other.__keys_)),
|
||||
__compare_(__other.__compare_) {}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(flat_multiset&& __other, const _Allocator& __alloc)
|
||||
# if _LIBCPP_HAS_EXCEPTIONS
|
||||
try
|
||||
# endif // _LIBCPP_HAS_EXCEPTIONS
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc, std::move(__other.__keys_))),
|
||||
__compare_(std::move(__other.__compare_)) {
|
||||
__other.clear();
|
||||
# if _LIBCPP_HAS_EXCEPTIONS
|
||||
} catch (...) {
|
||||
__other.clear();
|
||||
throw;
|
||||
# endif // _LIBCPP_HAS_EXCEPTIONS
|
||||
}
|
||||
|
||||
template <class _InputIterator, class _Allocator>
|
||||
requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value)
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() {
|
||||
insert(__first, __last);
|
||||
}
|
||||
|
||||
template <class _InputIterator, class _Allocator>
|
||||
requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value)
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
flat_multiset(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) {
|
||||
insert(__first, __last);
|
||||
}
|
||||
|
||||
template <class _InputIterator, class _Allocator>
|
||||
requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value)
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
flat_multiset(sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __first, __last)), __compare_() {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");
|
||||
}
|
||||
|
||||
template <class _InputIterator, class _Allocator>
|
||||
requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value)
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
flat_multiset(sorted_equivalent_t,
|
||||
_InputIterator __first,
|
||||
_InputIterator __last,
|
||||
const key_compare& __comp,
|
||||
const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __first, __last)), __compare_(__comp) {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");
|
||||
}
|
||||
|
||||
template <_ContainerCompatibleRange<value_type> _Range, class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() {
|
||||
insert_range(std::forward<_Range>(__rg));
|
||||
}
|
||||
|
||||
template <_ContainerCompatibleRange<value_type> _Range, class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) {
|
||||
insert_range(std::forward<_Range>(__rg));
|
||||
}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(initializer_list<value_type> __il, const _Allocator& __alloc)
|
||||
: flat_multiset(__il.begin(), __il.end(), __alloc) {}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
flat_multiset(initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc)
|
||||
: flat_multiset(__il.begin(), __il.end(), __comp, __alloc) {}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(sorted_equivalent_t, initializer_list<value_type> __il, const _Allocator& __alloc)
|
||||
: flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __alloc) {}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset(
|
||||
sorted_equivalent_t, initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc)
|
||||
: flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __comp, __alloc) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(initializer_list<value_type> __il) {
|
||||
clear();
|
||||
insert(__il);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// copy/move assignment are not specified in the spec (defaulted)
|
||||
// but move assignment can potentially leave moved from object in an inconsistent
|
||||
// state if an exception is thrown
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(const flat_multiset&) = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(flat_multiset&& __other) noexcept(
|
||||
is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_Compare>) {
|
||||
auto __clear_other_guard = std::__make_scope_guard([&]() noexcept { __other.clear() /* noexcept */; });
|
||||
auto __clear_self_guard = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
|
||||
__keys_ = std::move(__other.__keys_);
|
||||
__compare_ = std::move(__other.__compare_);
|
||||
__clear_self_guard.__complete();
|
||||
return *this;
|
||||
}
|
||||
|
||||
// iterators
|
||||
_LIBCPP_HIDE_FROM_ABI iterator begin() noexcept { return iterator(std::as_const(__keys_).begin()); }
|
||||
_LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { return const_iterator(__keys_.begin()); }
|
||||
_LIBCPP_HIDE_FROM_ABI iterator end() noexcept { return iterator(std::as_const(__keys_).end()); }
|
||||
_LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { return const_iterator(__keys_.end()); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
|
||||
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
|
||||
_LIBCPP_HIDE_FROM_ABI reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
|
||||
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return begin(); }
|
||||
_LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return end(); }
|
||||
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
|
||||
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
|
||||
|
||||
// capacity
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __keys_.empty(); }
|
||||
_LIBCPP_HIDE_FROM_ABI size_type size() const noexcept { return __keys_.size(); }
|
||||
_LIBCPP_HIDE_FROM_ABI size_type max_size() const noexcept { return __keys_.max_size(); }
|
||||
|
||||
// [flat.multiset.modifiers], modifiers
|
||||
template <class... _Args>
|
||||
requires is_constructible_v<value_type, _Args...>
|
||||
_LIBCPP_HIDE_FROM_ABI iterator emplace(_Args&&... __args) {
|
||||
if constexpr (sizeof...(__args) == 1 && (is_same_v<remove_cvref_t<_Args>, _Key> && ...)) {
|
||||
return __emplace(std::forward<_Args>(__args)...);
|
||||
} else {
|
||||
return __emplace(_Key(std::forward<_Args>(__args)...));
|
||||
}
|
||||
}
|
||||
|
||||
template <class... _Args>
|
||||
requires is_constructible_v<value_type, _Args...>
|
||||
_LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __hint, _Args&&... __args) {
|
||||
if constexpr (sizeof...(__args) == 1 && (is_same_v<remove_cvref_t<_Args>, _Key> && ...)) {
|
||||
return __emplace_hint(std::move(__hint), std::forward<_Args>(__args)...);
|
||||
} else {
|
||||
return __emplace_hint(std::move(__hint), _Key(std::forward<_Args>(__args)...));
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return emplace(__x); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI iterator insert(value_type&& __x) { return emplace(std::move(__x)); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, const value_type& __x) {
|
||||
return emplace_hint(__hint, __x);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, value_type&& __x) {
|
||||
return emplace_hint(__hint, std::move(__x));
|
||||
}
|
||||
|
||||
template <class _InputIterator>
|
||||
requires __has_input_iterator_category<_InputIterator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) {
|
||||
if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) {
|
||||
__reserve(__last - __first);
|
||||
}
|
||||
__append_sort_merge</*WasSorted = */ false>(std::move(__first), std::move(__last));
|
||||
}
|
||||
|
||||
template <class _InputIterator>
|
||||
requires __has_input_iterator_category<_InputIterator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, _InputIterator __first, _InputIterator __last) {
|
||||
if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) {
|
||||
__reserve(__last - __first);
|
||||
}
|
||||
|
||||
__append_sort_merge</*WasSorted = */ true>(std::move(__first), std::move(__last));
|
||||
}
|
||||
|
||||
template <_ContainerCompatibleRange<value_type> _Range>
|
||||
_LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) {
|
||||
if constexpr (ranges::sized_range<_Range>) {
|
||||
__reserve(ranges::size(__range));
|
||||
}
|
||||
|
||||
__append_sort_merge</*WasSorted = */ false>(std::forward<_Range>(__range));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI void insert(initializer_list<value_type> __il) { insert(__il.begin(), __il.end()); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, initializer_list<value_type> __il) {
|
||||
insert(sorted_equivalent, __il.begin(), __il.end());
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI container_type extract() && {
|
||||
auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; });
|
||||
auto __ret = std::move(__keys_);
|
||||
return __ret;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI void replace(container_type&& __keys) {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys, __compare_), "Key container is not sorted");
|
||||
auto __guard = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
|
||||
__keys_ = std::move(__keys);
|
||||
__guard.__complete();
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI iterator erase(iterator __position) {
|
||||
auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
|
||||
auto __key_iter = __keys_.erase(__position.__base());
|
||||
__on_failure.__complete();
|
||||
return iterator(__key_iter);
|
||||
}
|
||||
|
||||
// The following overload is the same as the iterator overload
|
||||
// iterator erase(const_iterator __position);
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __x) {
|
||||
auto [__first, __last] = equal_range(__x);
|
||||
auto __res = __last - __first;
|
||||
erase(__first, __last);
|
||||
return __res;
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> &&
|
||||
!is_convertible_v<_Kp &&, const_iterator>)
|
||||
_LIBCPP_HIDE_FROM_ABI size_type erase(_Kp&& __x) {
|
||||
auto [__first, __last] = equal_range(__x);
|
||||
auto __res = __last - __first;
|
||||
erase(__first, __last);
|
||||
return __res;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) {
|
||||
auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
|
||||
auto __key_it = __keys_.erase(__first.__base(), __last.__base());
|
||||
__on_failure.__complete();
|
||||
return iterator(std::move(__key_it));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI void swap(flat_multiset& __y) noexcept {
|
||||
// warning: The spec has unconditional noexcept, which means that
|
||||
// if any of the following functions throw an exception,
|
||||
// std::terminate will be called
|
||||
// This is discussed in P3567, which hasn't been voted on yet.
|
||||
ranges::swap(__compare_, __y.__compare_);
|
||||
ranges::swap(__keys_, __y.__keys_);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI void clear() noexcept { __keys_.clear(); }
|
||||
|
||||
// observers
|
||||
_LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __compare_; }
|
||||
_LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return __compare_; }
|
||||
|
||||
// map operations
|
||||
_LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __x) { return __find_impl(*this, __x); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); }
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI iterator find(const _Kp& __x) {
|
||||
return __find_impl(*this, __x);
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI const_iterator find(const _Kp& __x) const {
|
||||
return __find_impl(*this, __x);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __x) const {
|
||||
auto [__first, __last] = equal_range(__x);
|
||||
return __last - __first;
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI size_type count(const _Kp& __x) const {
|
||||
auto [__first, __last] = equal_range(__x);
|
||||
return __last - __first;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __x) const { return find(__x) != end(); }
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI bool contains(const _Kp& __x) const {
|
||||
return find(__x) != end();
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __x) {
|
||||
const auto& __keys = __keys_;
|
||||
return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __x) const {
|
||||
return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_));
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Kp& __x) {
|
||||
const auto& __keys = __keys_;
|
||||
return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_));
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Kp& __x) const {
|
||||
return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __x) {
|
||||
const auto& __keys = __keys_;
|
||||
return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __x) const {
|
||||
return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_));
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _Kp& __x) {
|
||||
const auto& __keys = __keys_;
|
||||
return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_));
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Kp& __x) const {
|
||||
return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __x) {
|
||||
return __equal_range_impl(*this, __x);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __x) const {
|
||||
return __equal_range_impl(*this, __x);
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _Kp& __x) {
|
||||
return __equal_range_impl(*this, __x);
|
||||
}
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _Kp& __x) const {
|
||||
return __equal_range_impl(*this, __x);
|
||||
}
|
||||
|
||||
friend _LIBCPP_HIDE_FROM_ABI bool operator==(const flat_multiset& __x, const flat_multiset& __y) {
|
||||
return ranges::equal(__x, __y);
|
||||
}
|
||||
|
||||
friend _LIBCPP_HIDE_FROM_ABI auto operator<=>(const flat_multiset& __x, const flat_multiset& __y) {
|
||||
return std::lexicographical_compare_three_way(
|
||||
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
|
||||
}
|
||||
|
||||
friend _LIBCPP_HIDE_FROM_ABI void swap(flat_multiset& __x, flat_multiset& __y) noexcept { __x.swap(__y); }
|
||||
|
||||
private:
|
||||
template <bool _WasSorted, class... _Args>
|
||||
_LIBCPP_HIDE_FROM_ABI void __append_sort_merge(_Args&&... __args) {
|
||||
auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
|
||||
size_type __old_size = size();
|
||||
__flat_set_utils::__append(*this, std::forward<_Args>(__args)...);
|
||||
if constexpr (!_WasSorted) {
|
||||
ranges::sort(__keys_.begin() + __old_size, __keys_.end(), __compare_);
|
||||
} else {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
|
||||
ranges::is_sorted(__keys_ | ranges::views::drop(__old_size)), "Key container is not sorted");
|
||||
}
|
||||
ranges::inplace_merge(__keys_.begin(), __keys_.begin() + __old_size, __keys_.end(), __compare_);
|
||||
__on_failure.__complete();
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
_LIBCPP_HIDE_FROM_ABI iterator __emplace(_Kp&& __key) {
|
||||
auto __it = upper_bound(__key);
|
||||
return __flat_set_utils::__emplace_exact_pos(*this, __it, std::forward<_Kp>(__key));
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
_LIBCPP_HIDE_FROM_ABI iterator __emplace_hint(const_iterator __hint, _Kp&& __key) {
|
||||
auto __prev_larger = __hint != cbegin() && __compare_(__key, *std::prev(__hint));
|
||||
auto __next_smaller = __hint != cend() && __compare_(*__hint, __key);
|
||||
|
||||
if (!__prev_larger && !__next_smaller) [[likely]] {
|
||||
// hint correct, just use exact hint iterator
|
||||
} else if (__prev_larger && !__next_smaller) {
|
||||
// the hint position is more to the right than the key should have been.
|
||||
// we want to emplace the element to a position as right as possible
|
||||
// e.g. Insert new element "2" in the following range
|
||||
// 1, 1, 2, 2, 2, 3, 4, 6
|
||||
// ^
|
||||
// |
|
||||
// hint
|
||||
// We want to insert "2" after the last existing "2"
|
||||
__hint = std::upper_bound(begin(), __hint, __key, __compare_);
|
||||
} else {
|
||||
_LIBCPP_ASSERT_INTERNAL(!__prev_larger && __next_smaller, "this means that the multiset is not sorted");
|
||||
|
||||
// the hint position is more to the left than the key should have been.
|
||||
// we want to emplace the element to a position as left as possible
|
||||
// 1, 1, 2, 2, 2, 3, 4, 6
|
||||
// ^
|
||||
// |
|
||||
// hint
|
||||
// We want to insert "2" before the first existing "2"
|
||||
__hint = std::lower_bound(__hint, end(), __key, __compare_);
|
||||
}
|
||||
return __flat_set_utils::__emplace_exact_pos(*this, __hint, std::forward<_Kp>(__key));
|
||||
}
|
||||
|
||||
template <class _Self, class _Kp>
|
||||
_LIBCPP_HIDE_FROM_ABI static auto __find_impl(_Self&& __self, const _Kp& __key) {
|
||||
auto __it = __self.lower_bound(__key);
|
||||
auto __last = __self.end();
|
||||
if (__it == __last || __self.__compare_(__key, *__it)) {
|
||||
return __last;
|
||||
}
|
||||
return __it;
|
||||
}
|
||||
|
||||
template <class _Self, class _Kp>
|
||||
_LIBCPP_HIDE_FROM_ABI static auto __equal_range_impl(_Self&& __self, const _Kp& __key) {
|
||||
using __iter = _If<is_const_v<__libcpp_remove_reference_t<_Self>>, const_iterator, iterator>;
|
||||
auto [__key_first, __key_last] =
|
||||
std::equal_range(__self.__keys_.begin(), __self.__keys_.end(), __key, __self.__compare_);
|
||||
return std::make_pair(__iter(__key_first), __iter(__key_last));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) {
|
||||
if constexpr (__container_traits<_KeyContainer>::__reservable) {
|
||||
__keys_.reserve(__size);
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Key2, class _Compare2, class _KeyContainer2, class _Predicate>
|
||||
friend typename flat_multiset<_Key2, _Compare2, _KeyContainer2>::size_type
|
||||
erase_if(flat_multiset<_Key2, _Compare2, _KeyContainer2>&, _Predicate);
|
||||
|
||||
_KeyContainer __keys_;
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_;
|
||||
|
||||
struct __key_equiv {
|
||||
_LIBCPP_HIDE_FROM_ABI __key_equiv(key_compare __c) : __comp_(__c) {}
|
||||
_LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const {
|
||||
return !__comp_(std::get<0>(__x), std::get<0>(__y)) && !__comp_(std::get<0>(__y), std::get<0>(__x));
|
||||
}
|
||||
key_compare __comp_;
|
||||
};
|
||||
};
|
||||
|
||||
template <class _KeyContainer, class _Compare = less<typename _KeyContainer::value_type>>
|
||||
requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
|
||||
is_invocable_v<const _Compare&,
|
||||
const typename _KeyContainer::value_type&,
|
||||
const typename _KeyContainer::value_type&>)
|
||||
flat_multiset(_KeyContainer, _Compare = _Compare())
|
||||
-> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
|
||||
|
||||
template <class _KeyContainer, class _Allocator>
|
||||
requires(uses_allocator_v<_KeyContainer, _Allocator> && !__is_allocator<_KeyContainer>::value)
|
||||
flat_multiset(_KeyContainer, _Allocator)
|
||||
-> flat_multiset<typename _KeyContainer::value_type, less<typename _KeyContainer::value_type>, _KeyContainer>;
|
||||
|
||||
template <class _KeyContainer, class _Compare, class _Allocator>
|
||||
requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
|
||||
uses_allocator_v<_KeyContainer, _Allocator> &&
|
||||
is_invocable_v<const _Compare&,
|
||||
const typename _KeyContainer::value_type&,
|
||||
const typename _KeyContainer::value_type&>)
|
||||
flat_multiset(_KeyContainer, _Compare, _Allocator)
|
||||
-> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
|
||||
|
||||
template <class _KeyContainer, class _Compare = less<typename _KeyContainer::value_type>>
|
||||
requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
|
||||
is_invocable_v<const _Compare&,
|
||||
const typename _KeyContainer::value_type&,
|
||||
const typename _KeyContainer::value_type&>)
|
||||
flat_multiset(sorted_equivalent_t, _KeyContainer, _Compare = _Compare())
|
||||
-> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
|
||||
|
||||
template <class _KeyContainer, class _Allocator>
|
||||
requires(uses_allocator_v<_KeyContainer, _Allocator> && !__is_allocator<_KeyContainer>::value)
|
||||
flat_multiset(sorted_equivalent_t, _KeyContainer, _Allocator)
|
||||
-> flat_multiset<typename _KeyContainer::value_type, less<typename _KeyContainer::value_type>, _KeyContainer>;
|
||||
|
||||
template <class _KeyContainer, class _Compare, class _Allocator>
|
||||
requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
|
||||
uses_allocator_v<_KeyContainer, _Allocator> &&
|
||||
is_invocable_v<const _Compare&,
|
||||
const typename _KeyContainer::value_type&,
|
||||
const typename _KeyContainer::value_type&>)
|
||||
flat_multiset(sorted_equivalent_t, _KeyContainer, _Compare, _Allocator)
|
||||
-> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
|
||||
|
||||
template <class _InputIterator, class _Compare = less<__iter_value_type<_InputIterator>>>
|
||||
requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value)
|
||||
flat_multiset(_InputIterator, _InputIterator, _Compare = _Compare())
|
||||
-> flat_multiset<__iter_value_type<_InputIterator>, _Compare>;
|
||||
|
||||
template <class _InputIterator, class _Compare = less<__iter_value_type<_InputIterator>>>
|
||||
requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value)
|
||||
flat_multiset(sorted_equivalent_t, _InputIterator, _InputIterator, _Compare = _Compare())
|
||||
-> flat_multiset<__iter_value_type<_InputIterator>, _Compare>;
|
||||
|
||||
template <ranges::input_range _Range,
|
||||
class _Compare = less<ranges::range_value_t<_Range>>,
|
||||
class _Allocator = allocator<ranges::range_value_t<_Range>>,
|
||||
class = __enable_if_t<!__is_allocator<_Compare>::value && __is_allocator<_Allocator>::value>>
|
||||
flat_multiset(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) -> flat_multiset<
|
||||
ranges::range_value_t<_Range>,
|
||||
_Compare,
|
||||
vector<ranges::range_value_t<_Range>, __allocator_traits_rebind_t<_Allocator, ranges::range_value_t<_Range>>>>;
|
||||
|
||||
template <ranges::input_range _Range, class _Allocator, class = __enable_if_t<__is_allocator<_Allocator>::value>>
|
||||
flat_multiset(from_range_t, _Range&&, _Allocator) -> flat_multiset<
|
||||
ranges::range_value_t<_Range>,
|
||||
less<ranges::range_value_t<_Range>>,
|
||||
vector<ranges::range_value_t<_Range>, __allocator_traits_rebind_t<_Allocator, ranges::range_value_t<_Range>>>>;
|
||||
|
||||
template <class _Key, class _Compare = less<_Key>>
|
||||
requires(!__is_allocator<_Compare>::value)
|
||||
flat_multiset(initializer_list<_Key>, _Compare = _Compare()) -> flat_multiset<_Key, _Compare>;
|
||||
|
||||
template <class _Key, class _Compare = less<_Key>>
|
||||
requires(!__is_allocator<_Compare>::value)
|
||||
flat_multiset(sorted_equivalent_t, initializer_list<_Key>, _Compare = _Compare()) -> flat_multiset<_Key, _Compare>;
|
||||
|
||||
template <class _Key, class _Compare, class _KeyContainer, class _Allocator>
|
||||
struct uses_allocator<flat_multiset<_Key, _Compare, _KeyContainer>, _Allocator>
|
||||
: bool_constant<uses_allocator_v<_KeyContainer, _Allocator> > {};
|
||||
|
||||
template <class _Key, class _Compare, class _KeyContainer, class _Predicate>
|
||||
_LIBCPP_HIDE_FROM_ABI typename flat_multiset<_Key, _Compare, _KeyContainer>::size_type
|
||||
erase_if(flat_multiset<_Key, _Compare, _KeyContainer>& __flat_multiset, _Predicate __pred) {
|
||||
auto __guard = std::__make_exception_guard([&] { __flat_multiset.clear(); });
|
||||
auto __it =
|
||||
std::remove_if(__flat_multiset.__keys_.begin(), __flat_multiset.__keys_.end(), [&](const auto& __e) -> bool {
|
||||
return static_cast<bool>(__pred(__e));
|
||||
});
|
||||
auto __res = __flat_multiset.__keys_.end() - __it;
|
||||
__flat_multiset.__keys_.erase(__it, __flat_multiset.__keys_.end());
|
||||
__guard.__complete();
|
||||
return __res;
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___FLAT_MAP_FLAT_MULTISET_H
|
||||
874
lib/libcxx/include/__flat_set/flat_set.h
vendored
Normal file
874
lib/libcxx/include/__flat_set/flat_set.h
vendored
Normal file
|
|
@ -0,0 +1,874 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___FLAT_SET_FLAT_SET_H
|
||||
#define _LIBCPP___FLAT_SET_FLAT_SET_H
|
||||
|
||||
#include <__algorithm/lexicographical_compare_three_way.h>
|
||||
#include <__algorithm/lower_bound.h>
|
||||
#include <__algorithm/min.h>
|
||||
#include <__algorithm/ranges_adjacent_find.h>
|
||||
#include <__algorithm/ranges_equal.h>
|
||||
#include <__algorithm/ranges_inplace_merge.h>
|
||||
#include <__algorithm/ranges_sort.h>
|
||||
#include <__algorithm/ranges_unique.h>
|
||||
#include <__algorithm/remove_if.h>
|
||||
#include <__algorithm/upper_bound.h>
|
||||
#include <__assert>
|
||||
#include <__compare/synth_three_way.h>
|
||||
#include <__concepts/swappable.h>
|
||||
#include <__config>
|
||||
#include <__cstddef/ptrdiff_t.h>
|
||||
#include <__flat_map/sorted_unique.h>
|
||||
#include <__flat_set/ra_iterator.h>
|
||||
#include <__flat_set/utils.h>
|
||||
#include <__functional/invoke.h>
|
||||
#include <__functional/is_transparent.h>
|
||||
#include <__functional/operations.h>
|
||||
#include <__fwd/vector.h>
|
||||
#include <__iterator/concepts.h>
|
||||
#include <__iterator/distance.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__iterator/next.h>
|
||||
#include <__iterator/prev.h>
|
||||
#include <__iterator/ranges_iterator_traits.h>
|
||||
#include <__iterator/reverse_iterator.h>
|
||||
#include <__memory/allocator_traits.h>
|
||||
#include <__memory/uses_allocator.h>
|
||||
#include <__memory/uses_allocator_construction.h>
|
||||
#include <__ranges/access.h>
|
||||
#include <__ranges/concepts.h>
|
||||
#include <__ranges/container_compatible_range.h>
|
||||
#include <__ranges/drop_view.h>
|
||||
#include <__ranges/from_range.h>
|
||||
#include <__ranges/ref_view.h>
|
||||
#include <__ranges/size.h>
|
||||
#include <__ranges/subrange.h>
|
||||
#include <__type_traits/conjunction.h>
|
||||
#include <__type_traits/container_traits.h>
|
||||
#include <__type_traits/invoke.h>
|
||||
#include <__type_traits/is_allocator.h>
|
||||
#include <__type_traits/is_const.h>
|
||||
#include <__type_traits/is_nothrow_constructible.h>
|
||||
#include <__type_traits/is_same.h>
|
||||
#include <__type_traits/remove_reference.h>
|
||||
#include <__utility/as_const.h>
|
||||
#include <__utility/exception_guard.h>
|
||||
#include <__utility/move.h>
|
||||
#include <__utility/pair.h>
|
||||
#include <__utility/scope_guard.h>
|
||||
#include <__vector/vector.h>
|
||||
#include <initializer_list>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
template <class _Key, class _Compare = less<_Key>, class _KeyContainer = vector<_Key>>
|
||||
class flat_set {
|
||||
template <class, class, class>
|
||||
friend class flat_set;
|
||||
|
||||
friend __flat_set_utils;
|
||||
|
||||
static_assert(is_same_v<_Key, typename _KeyContainer::value_type>);
|
||||
static_assert(!is_same_v<_KeyContainer, std::vector<bool>>, "vector<bool> is not a sequence container");
|
||||
|
||||
using __key_iterator _LIBCPP_NODEBUG = typename _KeyContainer::const_iterator;
|
||||
|
||||
public:
|
||||
// types
|
||||
using key_type = _Key;
|
||||
using value_type = _Key;
|
||||
using key_compare = __type_identity_t<_Compare>;
|
||||
using value_compare = _Compare;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using size_type = typename _KeyContainer::size_type;
|
||||
using difference_type = typename _KeyContainer::difference_type;
|
||||
using iterator = __ra_iterator<flat_set, typename _KeyContainer::const_iterator>;
|
||||
using const_iterator = iterator;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
using container_type = _KeyContainer;
|
||||
|
||||
public:
|
||||
// [flat.set.cons], construct/copy/destroy
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set() noexcept(is_nothrow_default_constructible_v<_KeyContainer> && is_nothrow_default_constructible_v<_Compare>)
|
||||
: __keys_(), __compare_() {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(const flat_set&) = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(flat_set&& __other) noexcept(
|
||||
is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_Compare>)
|
||||
# if _LIBCPP_HAS_EXCEPTIONS
|
||||
try
|
||||
# endif // _LIBCPP_HAS_EXCEPTIONS
|
||||
: __keys_(std::move(__other.__keys_)), __compare_(std::move(__other.__compare_)) {
|
||||
__other.clear();
|
||||
# if _LIBCPP_HAS_EXCEPTIONS
|
||||
} catch (...) {
|
||||
__other.clear();
|
||||
// gcc does not like the `throw` keyword in a conditionally noexcept function
|
||||
if constexpr (!(is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_Compare>)) {
|
||||
throw;
|
||||
}
|
||||
# endif // _LIBCPP_HAS_EXCEPTIONS
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_set(const key_compare& __comp)
|
||||
: __keys_(), __compare_(__comp) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
_LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_set(container_type __keys, const key_compare& __comp = key_compare())
|
||||
: __keys_(std::move(__keys)), __compare_(__comp) {
|
||||
__sort_and_unique();
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set(sorted_unique_t, container_type __keys, const key_compare& __comp = key_compare())
|
||||
: __keys_(std::move(__keys)), __compare_(__comp) {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
|
||||
__is_sorted_and_unique(__keys_), "Either the key container is not sorted or it contains duplicates");
|
||||
}
|
||||
|
||||
template <class _InputIterator>
|
||||
requires __has_input_iterator_category<_InputIterator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare())
|
||||
: __keys_(), __compare_(__comp) {
|
||||
insert(__first, __last);
|
||||
}
|
||||
|
||||
template <class _InputIterator>
|
||||
requires __has_input_iterator_category<_InputIterator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set(sorted_unique_t, _InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare())
|
||||
: __keys_(__first, __last), __compare_(__comp) {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
|
||||
__is_sorted_and_unique(__keys_), "Either the key container is not sorted or it contains duplicates");
|
||||
}
|
||||
|
||||
template <_ContainerCompatibleRange<value_type> _Range>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(from_range_t, _Range&& __rg)
|
||||
: flat_set(from_range, std::forward<_Range>(__rg), key_compare()) {}
|
||||
|
||||
template <_ContainerCompatibleRange<value_type> _Range>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(from_range_t, _Range&& __rg, const key_compare& __comp)
|
||||
: flat_set(__comp) {
|
||||
insert_range(std::forward<_Range>(__rg));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set(initializer_list<value_type> __il, const key_compare& __comp = key_compare())
|
||||
: flat_set(__il.begin(), __il.end(), __comp) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set(sorted_unique_t, initializer_list<value_type> __il, const key_compare& __comp = key_compare())
|
||||
: flat_set(sorted_unique, __il.begin(), __il.end(), __comp) {}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 explicit flat_set(const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() {}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(const key_compare& __comp, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) {}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(const container_type& __keys, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_() {
|
||||
__sort_and_unique();
|
||||
}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set(const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_(__comp) {
|
||||
__sort_and_unique();
|
||||
}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set(sorted_unique_t, const container_type& __keys, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_() {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
|
||||
__is_sorted_and_unique(__keys_), "Either the key container is not sorted or it contains duplicates");
|
||||
}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set(sorted_unique_t, const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_(__comp) {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
|
||||
__is_sorted_and_unique(__keys_), "Either the key container is not sorted or it contains duplicates");
|
||||
}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(const flat_set& __other, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __other.__keys_)),
|
||||
__compare_(__other.__compare_) {}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(flat_set&& __other, const _Allocator& __alloc)
|
||||
# if _LIBCPP_HAS_EXCEPTIONS
|
||||
try
|
||||
# endif // _LIBCPP_HAS_EXCEPTIONS
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc, std::move(__other.__keys_))),
|
||||
__compare_(std::move(__other.__compare_)) {
|
||||
__other.clear();
|
||||
# if _LIBCPP_HAS_EXCEPTIONS
|
||||
} catch (...) {
|
||||
__other.clear();
|
||||
throw;
|
||||
# endif // _LIBCPP_HAS_EXCEPTIONS
|
||||
}
|
||||
|
||||
template <class _InputIterator, class _Allocator>
|
||||
requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value)
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() {
|
||||
insert(__first, __last);
|
||||
}
|
||||
|
||||
template <class _InputIterator, class _Allocator>
|
||||
requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value)
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) {
|
||||
insert(__first, __last);
|
||||
}
|
||||
|
||||
template <class _InputIterator, class _Allocator>
|
||||
requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value)
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set(sorted_unique_t, _InputIterator __first, _InputIterator __last, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __first, __last)), __compare_() {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
|
||||
__is_sorted_and_unique(__keys_), "Either the key container is not sorted or it contains duplicates");
|
||||
}
|
||||
|
||||
template <class _InputIterator, class _Allocator>
|
||||
requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value)
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(
|
||||
sorted_unique_t,
|
||||
_InputIterator __first,
|
||||
_InputIterator __last,
|
||||
const key_compare& __comp,
|
||||
const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc, __first, __last)), __compare_(__comp) {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
|
||||
__is_sorted_and_unique(__keys_), "Either the key container is not sorted or it contains duplicates");
|
||||
}
|
||||
|
||||
template <_ContainerCompatibleRange<value_type> _Range, class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set(from_range_t, _Range&& __rg, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() {
|
||||
insert_range(std::forward<_Range>(__rg));
|
||||
}
|
||||
|
||||
template <_ContainerCompatibleRange<value_type> _Range, class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc)
|
||||
: __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) {
|
||||
insert_range(std::forward<_Range>(__rg));
|
||||
}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set(initializer_list<value_type> __il, const _Allocator& __alloc)
|
||||
: flat_set(__il.begin(), __il.end(), __alloc) {}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set(initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc)
|
||||
: flat_set(__il.begin(), __il.end(), __comp, __alloc) {}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set(sorted_unique_t, initializer_list<value_type> __il, const _Allocator& __alloc)
|
||||
: flat_set(sorted_unique, __il.begin(), __il.end(), __alloc) {}
|
||||
|
||||
template <class _Allocator>
|
||||
requires uses_allocator<container_type, _Allocator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
flat_set(sorted_unique_t, initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc)
|
||||
: flat_set(sorted_unique, __il.begin(), __il.end(), __comp, __alloc) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set& operator=(initializer_list<value_type> __il) {
|
||||
clear();
|
||||
insert(__il);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set& operator=(const flat_set&) = default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 flat_set& operator=(flat_set&& __other) noexcept(
|
||||
is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_Compare>) {
|
||||
// No matter what happens, we always want to clear the other container before returning
|
||||
// since we moved from it
|
||||
auto __clear_other_guard = std::__make_scope_guard([&]() noexcept { __other.clear() /* noexcept */; });
|
||||
{
|
||||
// If an exception is thrown, we have no choice but to clear *this to preserve invariants
|
||||
auto __on_exception = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
|
||||
__keys_ = std::move(__other.__keys_);
|
||||
__compare_ = std::move(__other.__compare_);
|
||||
__on_exception.__complete();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// iterators
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator begin() noexcept {
|
||||
return iterator(std::as_const(__keys_).begin());
|
||||
}
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator begin() const noexcept {
|
||||
return const_iterator(__keys_.begin());
|
||||
}
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator end() noexcept {
|
||||
return iterator(std::as_const(__keys_).end());
|
||||
}
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator end() const noexcept {
|
||||
return const_iterator(__keys_.end());
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rbegin() noexcept {
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rbegin() const noexcept {
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 reverse_iterator rend() noexcept {
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator rend() const noexcept {
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cbegin() const noexcept { return begin(); }
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator cend() const noexcept { return end(); }
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crbegin() const noexcept {
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_reverse_iterator crend() const noexcept {
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
// [flat.set.capacity], capacity
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool empty() const noexcept {
|
||||
return __keys_.empty();
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type size() const noexcept { return __keys_.size(); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type max_size() const noexcept { return __keys_.max_size(); }
|
||||
|
||||
// [flat.set.modifiers], modifiers
|
||||
template <class... _Args>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, bool> emplace(_Args&&... __args) {
|
||||
if constexpr (sizeof...(__args) == 1 && (is_same_v<remove_cvref_t<_Args>, _Key> && ...)) {
|
||||
return __emplace(std::forward<_Args>(__args)...);
|
||||
} else {
|
||||
return __emplace(_Key(std::forward<_Args>(__args)...));
|
||||
}
|
||||
}
|
||||
|
||||
template <class... _Args>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator emplace_hint(const_iterator __hint, _Args&&... __args) {
|
||||
if constexpr (sizeof...(__args) == 1 && (is_same_v<remove_cvref_t<_Args>, _Key> && ...)) {
|
||||
return __emplace_hint(std::move(__hint), std::forward<_Args>(__args)...);
|
||||
} else {
|
||||
return __emplace_hint(std::move(__hint), _Key(std::forward<_Args>(__args)...));
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, bool> insert(const value_type& __x) {
|
||||
return emplace(__x);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, bool> insert(value_type&& __x) {
|
||||
return emplace(std::move(__x));
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires(__is_transparent_v<_Compare> && is_constructible_v<value_type, _Kp>)
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, bool> insert(_Kp&& __x) {
|
||||
return __emplace(std::forward<_Kp>(__x));
|
||||
}
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, const value_type& __x) {
|
||||
return emplace_hint(__hint, __x);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, value_type&& __x) {
|
||||
return emplace_hint(__hint, std::move(__x));
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires(__is_transparent_v<_Compare> && is_constructible_v<value_type, _Kp>)
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator insert(const_iterator __hint, _Kp&& __x) {
|
||||
return __emplace_hint(__hint, std::forward<_Kp>(__x));
|
||||
}
|
||||
|
||||
template <class _InputIterator>
|
||||
requires __has_input_iterator_category<_InputIterator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(_InputIterator __first, _InputIterator __last) {
|
||||
if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) {
|
||||
__reserve(__last - __first);
|
||||
}
|
||||
__append_sort_merge_unique</*WasSorted = */ false>(std::move(__first), std::move(__last));
|
||||
}
|
||||
|
||||
template <class _InputIterator>
|
||||
requires __has_input_iterator_category<_InputIterator>::value
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
|
||||
insert(sorted_unique_t, _InputIterator __first, _InputIterator __last) {
|
||||
if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) {
|
||||
__reserve(__last - __first);
|
||||
}
|
||||
|
||||
__append_sort_merge_unique</*WasSorted = */ true>(std::move(__first), std::move(__last));
|
||||
}
|
||||
|
||||
template <_ContainerCompatibleRange<value_type> _Range>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert_range(_Range&& __range) {
|
||||
if constexpr (ranges::sized_range<_Range>) {
|
||||
__reserve(ranges::size(__range));
|
||||
}
|
||||
|
||||
__append_sort_merge_unique</*WasSorted = */ false>(std::forward<_Range>(__range));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(initializer_list<value_type> __il) {
|
||||
insert(__il.begin(), __il.end());
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void insert(sorted_unique_t, initializer_list<value_type> __il) {
|
||||
insert(sorted_unique, __il.begin(), __il.end());
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 container_type extract() && {
|
||||
auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; });
|
||||
auto __ret = std::move(__keys_);
|
||||
return __ret;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void replace(container_type&& __keys) {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
|
||||
__is_sorted_and_unique(__keys), "Either the key container is not sorted or it contains duplicates");
|
||||
auto __guard = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
|
||||
__keys_ = std::move(__keys);
|
||||
__guard.__complete();
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(iterator __position) {
|
||||
auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
|
||||
auto __key_iter = __keys_.erase(__position.__base());
|
||||
__on_failure.__complete();
|
||||
return iterator(__key_iter);
|
||||
}
|
||||
|
||||
// The following overload is the same as the iterator overload
|
||||
// iterator erase(const_iterator __position);
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(const key_type& __x) {
|
||||
auto __iter = find(__x);
|
||||
if (__iter != end()) {
|
||||
erase(__iter);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> &&
|
||||
!is_convertible_v<_Kp &&, const_iterator>)
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type erase(_Kp&& __x) {
|
||||
auto [__first, __last] = equal_range(__x);
|
||||
auto __res = __last - __first;
|
||||
erase(__first, __last);
|
||||
return __res;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator erase(const_iterator __first, const_iterator __last) {
|
||||
auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
|
||||
auto __key_it = __keys_.erase(__first.__base(), __last.__base());
|
||||
__on_failure.__complete();
|
||||
return iterator(std::move(__key_it));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(flat_set& __y) noexcept {
|
||||
// warning: The spec has unconditional noexcept, which means that
|
||||
// if any of the following functions throw an exception,
|
||||
// std::terminate will be called.
|
||||
// This is discussed in P2767, which hasn't been voted on yet.
|
||||
ranges::swap(__compare_, __y.__compare_);
|
||||
ranges::swap(__keys_, __y.__keys_);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void clear() noexcept { __keys_.clear(); }
|
||||
|
||||
// observers
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 key_compare key_comp() const { return __compare_; }
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 value_compare value_comp() const { return __compare_; }
|
||||
|
||||
// set operations
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const key_type& __x) {
|
||||
return __find_impl(*this, __x);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const key_type& __x) const {
|
||||
return __find_impl(*this, __x);
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator find(const _Kp& __x) {
|
||||
return __find_impl(*this, __x);
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator find(const _Kp& __x) const {
|
||||
return __find_impl(*this, __x);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const key_type& __x) const {
|
||||
return contains(__x) ? 1 : 0;
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 size_type count(const _Kp& __x) const {
|
||||
return contains(__x) ? 1 : 0;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const key_type& __x) const {
|
||||
return find(__x) != end();
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool contains(const _Kp& __x) const {
|
||||
return find(__x) != end();
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const key_type& __x) {
|
||||
const auto& __keys = __keys_;
|
||||
return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const key_type& __x) const {
|
||||
return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_));
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator lower_bound(const _Kp& __x) {
|
||||
const auto& __keys = __keys_;
|
||||
return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_));
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator lower_bound(const _Kp& __x) const {
|
||||
return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const key_type& __x) {
|
||||
const auto& __keys = __keys_;
|
||||
return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const key_type& __x) const {
|
||||
return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_));
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator upper_bound(const _Kp& __x) {
|
||||
const auto& __keys = __keys_;
|
||||
return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_));
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 const_iterator upper_bound(const _Kp& __x) const {
|
||||
return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_));
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, iterator> equal_range(const key_type& __x) {
|
||||
return __equal_range_impl(*this, __x);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<const_iterator, const_iterator>
|
||||
equal_range(const key_type& __x) const {
|
||||
return __equal_range_impl(*this, __x);
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, iterator> equal_range(const _Kp& __x) {
|
||||
return __equal_range_impl(*this, __x);
|
||||
}
|
||||
template <class _Kp>
|
||||
requires __is_transparent_v<_Compare>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<const_iterator, const_iterator>
|
||||
equal_range(const _Kp& __x) const {
|
||||
return __equal_range_impl(*this, __x);
|
||||
}
|
||||
|
||||
friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool operator==(const flat_set& __x, const flat_set& __y) {
|
||||
return ranges::equal(__x, __y);
|
||||
}
|
||||
|
||||
friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 auto
|
||||
operator<=>(const flat_set& __x, const flat_set& __y) {
|
||||
return std::lexicographical_compare_three_way(
|
||||
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
|
||||
}
|
||||
|
||||
friend _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void swap(flat_set& __x, flat_set& __y) noexcept {
|
||||
__x.swap(__y);
|
||||
}
|
||||
|
||||
private:
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __is_sorted_and_unique(auto&& __key_container) const {
|
||||
auto __greater_or_equal_to = [this](const auto& __x, const auto& __y) { return !__compare_(__x, __y); };
|
||||
return ranges::adjacent_find(__key_container, __greater_or_equal_to) == ranges::end(__key_container);
|
||||
}
|
||||
|
||||
// This function is only used in constructors. So there is not exception handling in this function.
|
||||
// If the function exits via an exception, there will be no flat_set object constructed, thus, there
|
||||
// is no invariant state to preserve
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __sort_and_unique() {
|
||||
ranges::sort(__keys_, __compare_);
|
||||
auto __dup_start = ranges::unique(__keys_, __key_equiv(__compare_)).begin();
|
||||
__keys_.erase(__dup_start, __keys_.end());
|
||||
}
|
||||
|
||||
template <bool _WasSorted, class... _Args>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __append_sort_merge_unique(_Args&&... __args) {
|
||||
auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
|
||||
size_type __old_size = size();
|
||||
__flat_set_utils::__append(*this, std::forward<_Args>(__args)...);
|
||||
if (size() != __old_size) {
|
||||
if constexpr (!_WasSorted) {
|
||||
ranges::sort(__keys_.begin() + __old_size, __keys_.end(), __compare_);
|
||||
} else {
|
||||
_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__is_sorted_and_unique(__keys_ | ranges::views::drop(__old_size)),
|
||||
"Either the key container is not sorted or it contains duplicates");
|
||||
}
|
||||
ranges::inplace_merge(__keys_.begin(), __keys_.begin() + __old_size, __keys_.end(), __compare_);
|
||||
|
||||
auto __dup_start = ranges::unique(__keys_, __key_equiv(__compare_)).begin();
|
||||
__keys_.erase(__dup_start, __keys_.end());
|
||||
}
|
||||
__on_failure.__complete();
|
||||
}
|
||||
|
||||
template <class _Self, class _Kp>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __find_impl(_Self&& __self, const _Kp& __key) {
|
||||
auto __it = __self.lower_bound(__key);
|
||||
auto __last = __self.end();
|
||||
if (__it == __last || __self.__compare_(__key, *__it)) {
|
||||
return __last;
|
||||
}
|
||||
return __it;
|
||||
}
|
||||
|
||||
template <class _Self, class _Kp>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto __equal_range_impl(_Self&& __self, const _Kp& __key) {
|
||||
using __iter = _If<is_const_v<__libcpp_remove_reference_t<_Self>>, const_iterator, iterator>;
|
||||
auto __it = std::lower_bound(__self.__keys_.begin(), __self.__keys_.end(), __key, __self.__compare_);
|
||||
auto __last = __self.__keys_.end();
|
||||
if (__it == __last || __self.__compare_(__key, *__it)) {
|
||||
return std::make_pair(__iter(__it), __iter(__it));
|
||||
}
|
||||
return std::make_pair(__iter(__it), __iter(std::next(__it)));
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 pair<iterator, bool> __emplace(_Kp&& __key) {
|
||||
auto __it = lower_bound(__key);
|
||||
if (__it == end() || __compare_(__key, *__it)) {
|
||||
return pair<iterator, bool>(__flat_set_utils::__emplace_exact_pos(*this, __it, std::forward<_Kp>(__key)), true);
|
||||
} else {
|
||||
return pair<iterator, bool>(std::move(__it), false);
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __is_hint_correct(const_iterator __hint, _Kp&& __key) {
|
||||
if (__hint != cbegin() && !__compare_(*std::prev(__hint), __key)) {
|
||||
return false;
|
||||
}
|
||||
if (__hint != cend() && __compare_(*__hint, __key)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class _Kp>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 iterator __emplace_hint(const_iterator __hint, _Kp&& __key) {
|
||||
if (__is_hint_correct(__hint, __key)) {
|
||||
if (__hint == cend() || __compare_(__key, *__hint)) {
|
||||
return __flat_set_utils::__emplace_exact_pos(*this, __hint, std::forward<_Kp>(__key));
|
||||
} else {
|
||||
// we already have an equal key
|
||||
return __hint;
|
||||
}
|
||||
} else {
|
||||
return __emplace(std::forward<_Kp>(__key)).first;
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void __reserve(size_t __size) {
|
||||
if constexpr (__container_traits<_KeyContainer>::__reservable) {
|
||||
__keys_.reserve(__size);
|
||||
}
|
||||
}
|
||||
|
||||
template <class _Key2, class _Compare2, class _KeyContainer2, class _Predicate>
|
||||
friend typename flat_set<_Key2, _Compare2, _KeyContainer2>::size_type _LIBCPP_CONSTEXPR_SINCE_CXX26
|
||||
erase_if(flat_set<_Key2, _Compare2, _KeyContainer2>&, _Predicate);
|
||||
|
||||
_KeyContainer __keys_;
|
||||
_LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_;
|
||||
|
||||
struct __key_equiv {
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_equiv(key_compare __c) : __comp_(__c) {}
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool
|
||||
operator()(const_reference __x, const_reference __y) const {
|
||||
return !__comp_(__x, __y) && !__comp_(__y, __x);
|
||||
}
|
||||
key_compare __comp_;
|
||||
};
|
||||
};
|
||||
|
||||
template <class _KeyContainer, class _Compare = less<typename _KeyContainer::value_type>>
|
||||
requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
|
||||
is_invocable_v<const _Compare&,
|
||||
const typename _KeyContainer::value_type&,
|
||||
const typename _KeyContainer::value_type&>)
|
||||
flat_set(_KeyContainer, _Compare = _Compare()) -> flat_set<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
|
||||
|
||||
template <class _KeyContainer, class _Allocator>
|
||||
requires(uses_allocator_v<_KeyContainer, _Allocator> && !__is_allocator<_KeyContainer>::value)
|
||||
flat_set(_KeyContainer, _Allocator)
|
||||
-> flat_set<typename _KeyContainer::value_type, less<typename _KeyContainer::value_type>, _KeyContainer>;
|
||||
|
||||
template <class _KeyContainer, class _Compare, class _Allocator>
|
||||
requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
|
||||
uses_allocator_v<_KeyContainer, _Allocator> &&
|
||||
is_invocable_v<const _Compare&,
|
||||
const typename _KeyContainer::value_type&,
|
||||
const typename _KeyContainer::value_type&>)
|
||||
flat_set(_KeyContainer, _Compare, _Allocator) -> flat_set<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
|
||||
|
||||
template <class _KeyContainer, class _Compare = less<typename _KeyContainer::value_type>>
|
||||
requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
|
||||
is_invocable_v<const _Compare&,
|
||||
const typename _KeyContainer::value_type&,
|
||||
const typename _KeyContainer::value_type&>)
|
||||
flat_set(sorted_unique_t, _KeyContainer, _Compare = _Compare())
|
||||
-> flat_set<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
|
||||
|
||||
template <class _KeyContainer, class _Allocator>
|
||||
requires(uses_allocator_v<_KeyContainer, _Allocator> && !__is_allocator<_KeyContainer>::value)
|
||||
flat_set(sorted_unique_t, _KeyContainer, _Allocator)
|
||||
-> flat_set<typename _KeyContainer::value_type, less<typename _KeyContainer::value_type>, _KeyContainer>;
|
||||
|
||||
template <class _KeyContainer, class _Compare, class _Allocator>
|
||||
requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
|
||||
uses_allocator_v<_KeyContainer, _Allocator> &&
|
||||
is_invocable_v<const _Compare&,
|
||||
const typename _KeyContainer::value_type&,
|
||||
const typename _KeyContainer::value_type&>)
|
||||
flat_set(sorted_unique_t, _KeyContainer, _Compare, _Allocator)
|
||||
-> flat_set<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
|
||||
|
||||
template <class _InputIterator, class _Compare = less<__iter_value_type<_InputIterator>>>
|
||||
requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value)
|
||||
flat_set(_InputIterator, _InputIterator, _Compare = _Compare())
|
||||
-> flat_set<__iter_value_type<_InputIterator>, _Compare>;
|
||||
|
||||
template <class _InputIterator, class _Compare = less<__iter_value_type<_InputIterator>>>
|
||||
requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value)
|
||||
flat_set(sorted_unique_t, _InputIterator, _InputIterator, _Compare = _Compare())
|
||||
-> flat_set<__iter_value_type<_InputIterator>, _Compare>;
|
||||
|
||||
template <ranges::input_range _Range,
|
||||
class _Compare = less<ranges::range_value_t<_Range>>,
|
||||
class _Allocator = allocator<ranges::range_value_t<_Range>>,
|
||||
class = __enable_if_t<!__is_allocator<_Compare>::value && __is_allocator<_Allocator>::value>>
|
||||
flat_set(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) -> flat_set<
|
||||
ranges::range_value_t<_Range>,
|
||||
_Compare,
|
||||
vector<ranges::range_value_t<_Range>, __allocator_traits_rebind_t<_Allocator, ranges::range_value_t<_Range>>>>;
|
||||
|
||||
template <ranges::input_range _Range, class _Allocator, class = __enable_if_t<__is_allocator<_Allocator>::value>>
|
||||
flat_set(from_range_t, _Range&&, _Allocator) -> flat_set<
|
||||
ranges::range_value_t<_Range>,
|
||||
less<ranges::range_value_t<_Range>>,
|
||||
vector<ranges::range_value_t<_Range>, __allocator_traits_rebind_t<_Allocator, ranges::range_value_t<_Range>>>>;
|
||||
|
||||
template <class _Key, class _Compare = less<_Key>>
|
||||
requires(!__is_allocator<_Compare>::value)
|
||||
flat_set(initializer_list<_Key>, _Compare = _Compare()) -> flat_set<_Key, _Compare>;
|
||||
|
||||
template <class _Key, class _Compare = less<_Key>>
|
||||
requires(!__is_allocator<_Compare>::value)
|
||||
flat_set(sorted_unique_t, initializer_list<_Key>, _Compare = _Compare()) -> flat_set<_Key, _Compare>;
|
||||
|
||||
template <class _Key, class _Compare, class _KeyContainer, class _Allocator>
|
||||
struct uses_allocator<flat_set<_Key, _Compare, _KeyContainer>, _Allocator>
|
||||
: bool_constant<uses_allocator_v<_KeyContainer, _Allocator>> {};
|
||||
|
||||
template <class _Key, class _Compare, class _KeyContainer, class _Predicate>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 typename flat_set<_Key, _Compare, _KeyContainer>::size_type
|
||||
erase_if(flat_set<_Key, _Compare, _KeyContainer>& __flat_set, _Predicate __pred) {
|
||||
auto __guard = std::__make_exception_guard([&] { __flat_set.clear(); });
|
||||
auto __it = std::remove_if(__flat_set.__keys_.begin(), __flat_set.__keys_.end(), [&](const auto& __e) -> bool {
|
||||
return static_cast<bool>(__pred(__e));
|
||||
});
|
||||
auto __res = __flat_set.__keys_.end() - __it;
|
||||
__flat_set.__keys_.erase(__it, __flat_set.__keys_.end());
|
||||
__guard.__complete();
|
||||
return __res;
|
||||
}
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___FLAT_SET_FLAT_SET_H
|
||||
157
lib/libcxx/include/__flat_set/ra_iterator.h
vendored
Normal file
157
lib/libcxx/include/__flat_set/ra_iterator.h
vendored
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___FLAT_SET_RA_ITERATOR_H
|
||||
#define _LIBCPP___FLAT_SET_RA_ITERATOR_H
|
||||
|
||||
#include "__type_traits/is_same.h"
|
||||
#include <__compare/three_way_comparable.h>
|
||||
#include <__config>
|
||||
#include <__iterator/incrementable_traits.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__type_traits/is_constructible.h>
|
||||
#include <__utility/move.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
/**
|
||||
* __ra_iterator is a random access iterator that wraps an underlying iterator.
|
||||
* It also stores the underlying container type in its type so that algorithms
|
||||
* can optimize based on the underlying container type, and to avoid inadvertently
|
||||
* mixing iterators coming from different containers..
|
||||
*/
|
||||
template <class _Container, class _Iterator>
|
||||
struct __ra_iterator {
|
||||
private:
|
||||
_Iterator __iter_;
|
||||
|
||||
friend _Container;
|
||||
|
||||
// note: checking the concept random_access_iterator does not work for incomplete types
|
||||
static_assert(_IsSame<typename iterator_traits<_Iterator>::iterator_category, random_access_iterator_tag>::value,
|
||||
"Underlying iterator must be a random access iterator");
|
||||
|
||||
public:
|
||||
using iterator_concept = random_access_iterator_tag; // deliberately lower contiguous_iterator
|
||||
using iterator_category = random_access_iterator_tag;
|
||||
using value_type = iter_value_t<_Iterator>;
|
||||
using difference_type = iter_difference_t<_Iterator>;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI __ra_iterator()
|
||||
requires is_default_constructible_v<_Iterator>
|
||||
= default;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI explicit constexpr __ra_iterator(_Iterator __iter) : __iter_(std::move(__iter)) {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr _Iterator __base() const noexcept(noexcept(_Iterator(__iter_))) { return __iter_; }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator*() const { return *__iter_; }
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator->() const
|
||||
requires requires { __iter_.operator->(); }
|
||||
{
|
||||
return __iter_.operator->();
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __ra_iterator& operator++() {
|
||||
++__iter_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __ra_iterator operator++(int) {
|
||||
__ra_iterator __tmp(*this);
|
||||
++*this;
|
||||
return __tmp;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __ra_iterator& operator--() {
|
||||
--__iter_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __ra_iterator operator--(int) {
|
||||
__ra_iterator __tmp(*this);
|
||||
--*this;
|
||||
return __tmp;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __ra_iterator& operator+=(difference_type __x) {
|
||||
__iter_ += __x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr __ra_iterator& operator-=(difference_type __x) {
|
||||
__iter_ -= __x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](difference_type __n) const { return *(*this + __n); }
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __ra_iterator& __x, const __ra_iterator& __y) {
|
||||
return __x.__iter_ == __y.__iter_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __ra_iterator& __x, const __ra_iterator& __y) {
|
||||
return __x.__iter_ < __y.__iter_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __ra_iterator& __x, const __ra_iterator& __y) {
|
||||
return __y < __x;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __ra_iterator& __x, const __ra_iterator& __y) {
|
||||
return !(__y < __x);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __ra_iterator& __x, const __ra_iterator& __y) {
|
||||
return !(__x < __y);
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __ra_iterator& __x, const __ra_iterator& __y)
|
||||
requires three_way_comparable<_Iterator>
|
||||
{
|
||||
return __x.__iter_ <=> __y.__iter_;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr __ra_iterator operator+(const __ra_iterator& __i, difference_type __n) {
|
||||
auto __tmp = __i;
|
||||
__tmp += __n;
|
||||
return __tmp;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr __ra_iterator operator+(difference_type __n, const __ra_iterator& __i) {
|
||||
return __i + __n;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr __ra_iterator operator-(const __ra_iterator& __i, difference_type __n) {
|
||||
auto __tmp = __i;
|
||||
__tmp -= __n;
|
||||
return __tmp;
|
||||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __ra_iterator& __x, const __ra_iterator& __y) {
|
||||
return __x.__iter_ - __y.__iter_;
|
||||
}
|
||||
};
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___FLAT_SET_RA_ITERATOR_H
|
||||
82
lib/libcxx/include/__flat_set/utils.h
vendored
Normal file
82
lib/libcxx/include/__flat_set/utils.h
vendored
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___FLAT_SET_UTILS_H
|
||||
#define _LIBCPP___FLAT_SET_UTILS_H
|
||||
|
||||
#include <__config>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__ranges/access.h>
|
||||
#include <__ranges/concepts.h>
|
||||
#include <__type_traits/container_traits.h>
|
||||
#include <__type_traits/decay.h>
|
||||
#include <__utility/exception_guard.h>
|
||||
#include <__utility/forward.h>
|
||||
#include <__utility/move.h>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
// These utilities are defined in a class instead of a namespace so that this class can be befriended more easily.
|
||||
struct __flat_set_utils {
|
||||
// Emplace a key into a flat_{multi}set, at the exact position that
|
||||
// __it point to, assuming that the key is not already present in the set.
|
||||
// When an exception is thrown during the emplacement, the function will clear the set if the container does not
|
||||
// have strong exception safety guarantee on emplacement.
|
||||
template <class _Set, class _Iter, class _KeyArg>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto
|
||||
__emplace_exact_pos(_Set& __set, _Iter&& __iter, _KeyArg&& __key) {
|
||||
using _KeyContainer = typename decay_t<_Set>::container_type;
|
||||
auto __on_failure = std::__make_exception_guard([&]() noexcept {
|
||||
if constexpr (!__container_traits<_KeyContainer>::__emplacement_has_strong_exception_safety_guarantee) {
|
||||
__set.clear() /* noexcept */;
|
||||
}
|
||||
});
|
||||
auto __key_it = __set.__keys_.emplace(__iter.__base(), std::forward<_KeyArg>(__key));
|
||||
__on_failure.__complete();
|
||||
return typename decay_t<_Set>::iterator(std::move(__key_it));
|
||||
}
|
||||
|
||||
template <class _Set, class _InputIterator>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static void
|
||||
__append(_Set& __set, _InputIterator __first, _InputIterator __last) {
|
||||
__set.__keys_.insert(__set.__keys_.end(), std::move(__first), std::move(__last));
|
||||
}
|
||||
|
||||
template <class _Set, class _Range>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static void __append(_Set& __set, _Range&& __rng) {
|
||||
if constexpr (requires { __set.__keys_.insert_range(__set.__keys_.end(), std::forward<_Range>(__rng)); }) {
|
||||
// C++23 Sequence Container should have insert_range member function
|
||||
// Note that not all Sequence Containers provide append_range.
|
||||
__set.__keys_.insert_range(__set.__keys_.end(), std::forward<_Range>(__rng));
|
||||
} else if constexpr (ranges::common_range<_Range> &&
|
||||
__has_input_iterator_category<ranges::iterator_t<_Range>>::value) {
|
||||
__set.__keys_.insert(__set.__keys_.end(), ranges::begin(__rng), ranges::end(__rng));
|
||||
} else {
|
||||
for (auto&& __x : __rng) {
|
||||
__set.__keys_.insert(__set.__keys_.end(), std::forward<decltype(__x)>(__x));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // #define _LIBCPP___FLAT_SET_UTILS_H
|
||||
29
lib/libcxx/include/__format/buffer.h
vendored
29
lib/libcxx/include/__format/buffer.h
vendored
|
|
@ -15,7 +15,6 @@
|
|||
#include <__algorithm/max.h>
|
||||
#include <__algorithm/min.h>
|
||||
#include <__algorithm/ranges_copy.h>
|
||||
#include <__algorithm/ranges_copy_n.h>
|
||||
#include <__algorithm/transform.h>
|
||||
#include <__algorithm/unwrap_iter.h>
|
||||
#include <__concepts/same_as.h>
|
||||
|
|
@ -33,7 +32,7 @@
|
|||
#include <__memory/allocator.h>
|
||||
#include <__memory/allocator_traits.h>
|
||||
#include <__memory/construct_at.h>
|
||||
#include <__memory/ranges_construct_at.h>
|
||||
#include <__memory/destroy.h>
|
||||
#include <__memory/uninitialized_algorithms.h>
|
||||
#include <__type_traits/add_pointer.h>
|
||||
#include <__type_traits/conditional.h>
|
||||
|
|
@ -180,7 +179,7 @@ private:
|
|||
/// The latter option allows formatted_size to use the output buffer without
|
||||
/// ever writing anything to the buffer.
|
||||
template <__fmt_char_type _CharT>
|
||||
class _LIBCPP_TEMPLATE_VIS __output_buffer {
|
||||
class __output_buffer {
|
||||
public:
|
||||
using value_type _LIBCPP_NODEBUG = _CharT;
|
||||
using __prepare_write_type _LIBCPP_NODEBUG = void (*)(__output_buffer<_CharT>&, size_t);
|
||||
|
|
@ -340,18 +339,18 @@ concept __insertable =
|
|||
|
||||
/// Extract the container type of a \ref back_insert_iterator.
|
||||
template <class _It>
|
||||
struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container {
|
||||
struct __back_insert_iterator_container {
|
||||
using type _LIBCPP_NODEBUG = void;
|
||||
};
|
||||
|
||||
template <__insertable _Container>
|
||||
struct _LIBCPP_TEMPLATE_VIS __back_insert_iterator_container<back_insert_iterator<_Container>> {
|
||||
struct __back_insert_iterator_container<back_insert_iterator<_Container>> {
|
||||
using type _LIBCPP_NODEBUG = _Container;
|
||||
};
|
||||
|
||||
// A dynamically growing buffer.
|
||||
template <__fmt_char_type _CharT>
|
||||
class _LIBCPP_TEMPLATE_VIS __allocating_buffer : public __output_buffer<_CharT> {
|
||||
class __allocating_buffer : public __output_buffer<_CharT> {
|
||||
public:
|
||||
__allocating_buffer(const __allocating_buffer&) = delete;
|
||||
__allocating_buffer& operator=(const __allocating_buffer&) = delete;
|
||||
|
|
@ -408,7 +407,7 @@ private:
|
|||
|
||||
// A buffer that directly writes to the underlying buffer.
|
||||
template <class _OutIt, __fmt_char_type _CharT>
|
||||
class _LIBCPP_TEMPLATE_VIS __direct_iterator_buffer : public __output_buffer<_CharT> {
|
||||
class __direct_iterator_buffer : public __output_buffer<_CharT> {
|
||||
public:
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __direct_iterator_buffer(_OutIt __out_it)
|
||||
: __direct_iterator_buffer{__out_it, nullptr} {}
|
||||
|
|
@ -437,7 +436,7 @@ private:
|
|||
|
||||
// A buffer that writes its output to the end of a container.
|
||||
template <class _OutIt, __fmt_char_type _CharT>
|
||||
class _LIBCPP_TEMPLATE_VIS __container_inserter_buffer : public __output_buffer<_CharT> {
|
||||
class __container_inserter_buffer : public __output_buffer<_CharT> {
|
||||
public:
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __container_inserter_buffer(_OutIt __out_it)
|
||||
: __container_inserter_buffer{__out_it, nullptr} {}
|
||||
|
|
@ -478,7 +477,7 @@ private:
|
|||
// Unlike the __container_inserter_buffer this class' performance does benefit
|
||||
// from allocating and then inserting.
|
||||
template <class _OutIt, __fmt_char_type _CharT>
|
||||
class _LIBCPP_TEMPLATE_VIS __iterator_buffer : public __allocating_buffer<_CharT> {
|
||||
class __iterator_buffer : public __allocating_buffer<_CharT> {
|
||||
public:
|
||||
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI explicit __iterator_buffer(_OutIt __out_it)
|
||||
: __allocating_buffer<_CharT>{}, __out_it_{std::move(__out_it)} {}
|
||||
|
|
@ -496,7 +495,7 @@ private:
|
|||
|
||||
// Selects the type of the buffer used for the output iterator.
|
||||
template <class _OutIt, __fmt_char_type _CharT>
|
||||
class _LIBCPP_TEMPLATE_VIS __buffer_selector {
|
||||
class __buffer_selector {
|
||||
using _Container _LIBCPP_NODEBUG = __back_insert_iterator_container<_OutIt>::type;
|
||||
|
||||
public:
|
||||
|
|
@ -510,7 +509,7 @@ public:
|
|||
|
||||
// A buffer that counts and limits the number of insertions.
|
||||
template <class _OutIt, __fmt_char_type _CharT>
|
||||
class _LIBCPP_TEMPLATE_VIS __format_to_n_buffer : private __buffer_selector<_OutIt, _CharT>::type {
|
||||
class __format_to_n_buffer : private __buffer_selector<_OutIt, _CharT>::type {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __buffer_selector<_OutIt, _CharT>::type;
|
||||
|
||||
|
|
@ -534,7 +533,7 @@ private:
|
|||
// Since formatted_size only needs to know the size, the output itself is
|
||||
// discarded.
|
||||
template <__fmt_char_type _CharT>
|
||||
class _LIBCPP_TEMPLATE_VIS __formatted_size_buffer : private __output_buffer<_CharT> {
|
||||
class __formatted_size_buffer : private __output_buffer<_CharT> {
|
||||
public:
|
||||
using _Base _LIBCPP_NODEBUG = __output_buffer<_CharT>;
|
||||
|
||||
|
|
@ -577,7 +576,7 @@ private:
|
|||
// This class uses its own buffer management, since using vector
|
||||
// would lead to a circular include with formatter for vector<bool>.
|
||||
template <__fmt_char_type _CharT>
|
||||
class _LIBCPP_TEMPLATE_VIS __retarget_buffer {
|
||||
class __retarget_buffer {
|
||||
using _Alloc _LIBCPP_NODEBUG = allocator<_CharT>;
|
||||
|
||||
public:
|
||||
|
|
@ -621,7 +620,7 @@ public:
|
|||
}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI ~__retarget_buffer() {
|
||||
ranges::destroy_n(__ptr_, __size_);
|
||||
std::destroy_n(__ptr_, __size_);
|
||||
allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_);
|
||||
}
|
||||
|
||||
|
|
@ -686,7 +685,7 @@ private:
|
|||
// guard is optimized away so there is no runtime overhead.
|
||||
std::uninitialized_move_n(__ptr_, __size_, __result.ptr);
|
||||
__guard.__complete();
|
||||
ranges::destroy_n(__ptr_, __size_);
|
||||
std::destroy_n(__ptr_, __size_);
|
||||
allocator_traits<_Alloc>::deallocate(__alloc_, __ptr_, __capacity_);
|
||||
|
||||
__ptr_ = __result.ptr;
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
|
|||
// adaptor headers. To use the format functions users already include <format>.
|
||||
|
||||
template <class _Adaptor, class _CharT>
|
||||
struct _LIBCPP_TEMPLATE_VIS __formatter_container_adaptor {
|
||||
struct __formatter_container_adaptor {
|
||||
private:
|
||||
using __maybe_const_container _LIBCPP_NODEBUG = __fmt_maybe_const<typename _Adaptor::container_type, _CharT>;
|
||||
using __maybe_const_adaptor _LIBCPP_NODEBUG = __maybe_const<is_const_v<__maybe_const_container>, _Adaptor>;
|
||||
|
|
@ -55,15 +55,15 @@ public:
|
|||
};
|
||||
|
||||
template <class _CharT, class _Tp, formattable<_CharT> _Container>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<queue<_Tp, _Container>, _CharT>
|
||||
struct formatter<queue<_Tp, _Container>, _CharT>
|
||||
: public __formatter_container_adaptor<queue<_Tp, _Container>, _CharT> {};
|
||||
|
||||
template <class _CharT, class _Tp, class _Container, class _Compare>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<priority_queue<_Tp, _Container, _Compare>, _CharT>
|
||||
struct formatter<priority_queue<_Tp, _Container, _Compare>, _CharT>
|
||||
: public __formatter_container_adaptor<priority_queue<_Tp, _Container, _Compare>, _CharT> {};
|
||||
|
||||
template <class _CharT, class _Tp, formattable<_CharT> _Container>
|
||||
struct _LIBCPP_TEMPLATE_VIS formatter<stack<_Tp, _Container>, _CharT>
|
||||
struct formatter<stack<_Tp, _Container>, _CharT>
|
||||
: public __formatter_container_adaptor<stack<_Tp, _Container>, _CharT> {};
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue