libcxx: update to LLVM 21

This commit is contained in:
Alex Rønne Petersen 2025-07-16 10:46:24 +02:00
parent e84e9d3a01
commit d9f0fbf983
No known key found for this signature in database
562 changed files with 16867 additions and 12974 deletions

View file

@ -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;
}

View file

@ -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*>

View file

@ -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;
}

View file

@ -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,

View file

@ -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);
}
}

View file

@ -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));
}

View file

@ -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

View file

@ -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

View 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

View file

@ -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<>());
}

View file

@ -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;

View file

@ -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*>

View file

@ -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*>

View 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

View file

@ -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{});
}

View file

@ -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:

View file

@ -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)};
}
};

View file

@ -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));

View file

@ -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

View file

@ -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) {

View file

@ -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);
}
};

View file

@ -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) {

View file

@ -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);
}
};

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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) {

View file

@ -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__)

View file

@ -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

View file

@ -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&>(

View file

@ -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;
}

View file

@ -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>

View file

@ -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

View file

@ -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

View file

@ -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,8 +267,8 @@ 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;
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);

View file

@ -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_); }

View file

@ -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;

View file

@ -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) {}
};

View file

@ -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)

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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));
}

View file

@ -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

View file

@ -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);
}

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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,27 +30,22 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 17
namespace __itoa {
template <typename _Tp, typename = void>
struct _LIBCPP_HIDDEN __traits_base;
template <typename _Tp>
struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) <= sizeof(uint32_t)>> {
struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) <= sizeof(uint32_t)> > {
using type = uint32_t;
/// The width estimation using a log10 algorithm.
///
/// 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;
}
@ -63,19 +59,16 @@ struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) <= sizeof(uin
};
template <typename _Tp>
struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) == sizeof(uint64_t)>> {
struct _LIBCPP_HIDDEN __traits_base<_Tp, __enable_if_t<sizeof(_Tp) == sizeof(uint64_t)> > {
using type = uint64_t;
/// The width estimation using a log10 algorithm.
///
/// 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

View file

@ -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,

View file

@ -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");

View file

@ -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
View 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

View file

@ -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

View file

@ -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
View 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

View file

@ -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;
};

View file

@ -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>

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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>

View file

@ -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

View file

@ -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,64 +86,106 @@ inline _LIBCPP_HIDE_FROM_ABI chrono::nanoseconds __safe_nanosecond_cast(chrono::
return nanoseconds(__result);
}
#if _LIBCPP_HAS_THREADS
template <class _Predicate>
void condition_variable::wait(unique_lock<mutex>& __lk, _Predicate __pred) {
while (!__pred())
wait(__lk);
}
class _LIBCPP_EXPORTED_FROM_ABI condition_variable {
__libcpp_condvar_t __cv_ = _LIBCPP_CONDVAR_INITIALIZER;
template <class _Clock, class _Duration>
cv_status condition_variable::wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t) {
using namespace chrono;
using __clock_tp_ns = time_point<_Clock, nanoseconds>;
public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR condition_variable() _NOEXCEPT = default;
typename _Clock::time_point __now = _Clock::now();
if (__t <= __now)
return cv_status::timeout;
__clock_tp_ns __t_ns = __clock_tp_ns(std::__safe_nanosecond_cast(__t.time_since_epoch()));
__do_timed_wait(__lk, __t_ns);
return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
}
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) {
while (!__pred()) {
if (wait_until(__lk, __t) == cv_status::timeout)
return __pred();
}
return true;
}
template <class _Rep, class _Period>
cv_status condition_variable::wait_for(unique_lock<mutex>& __lk, const chrono::duration<_Rep, _Period>& __d) {
using namespace chrono;
if (__d <= __d.zero())
return cv_status::timeout;
using __ns_rep = nanoseconds::rep;
steady_clock::time_point __c_now = steady_clock::now();
# if _LIBCPP_HAS_COND_CLOCKWAIT
using __clock_tp_ns = time_point<steady_clock, nanoseconds>;
__ns_rep __now_count_ns = std::__safe_nanosecond_cast(__c_now.time_since_epoch()).count();
# if _LIBCPP_HAS_TRIVIAL_CONDVAR_DESTRUCTION
~condition_variable() = default;
# else
using __clock_tp_ns = time_point<system_clock, nanoseconds>;
__ns_rep __now_count_ns = std::__safe_nanosecond_cast(system_clock::now().time_since_epoch()).count();
~condition_variable();
# endif
__ns_rep __d_ns_count = std::__safe_nanosecond_cast(__d).count();
condition_variable(const condition_variable&) = delete;
condition_variable& operator=(const condition_variable&) = delete;
if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) {
__do_timed_wait(__lk, __clock_tp_ns::max());
} else {
__do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count)));
void notify_one() _NOEXCEPT;
void notify_all() _NOEXCEPT;
void wait(unique_lock<mutex>& __lk) _NOEXCEPT;
template <class _Predicate>
_LIBCPP_HIDE_FROM_ABI void wait(unique_lock<mutex>& __lk, _Predicate __pred) {
while (!__pred())
wait(__lk);
}
return steady_clock::now() - __c_now < __d ? cv_status::no_timeout : cv_status::timeout;
}
template <class _Clock, class _Duration>
_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>;
typename _Clock::time_point __now = _Clock::now();
if (__t <= __now)
return cv_status::timeout;
__clock_tp_ns __t_ns = __clock_tp_ns(std::__safe_nanosecond_cast(__t.time_since_epoch()));
__do_timed_wait(__lk, __t_ns);
return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
}
template <class _Clock, class _Duration, class _Predicate>
_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();
}
return true;
}
template <class _Rep, class _Period>
_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;
using __ns_rep = nanoseconds::rep;
steady_clock::time_point __c_now = steady_clock::now();
# if _LIBCPP_HAS_COND_CLOCKWAIT
using __clock_tp_ns = time_point<steady_clock, nanoseconds>;
__ns_rep __now_count_ns = std::__safe_nanosecond_cast(__c_now.time_since_epoch()).count();
# else
using __clock_tp_ns = time_point<system_clock, nanoseconds>;
__ns_rep __now_count_ns = std::__safe_nanosecond_cast(system_clock::now().time_since_epoch()).count();
# endif
__ns_rep __d_ns_count = std::__safe_nanosecond_cast(__d).count();
if (__now_count_ns > numeric_limits<__ns_rep>::max() - __d_ns_count) {
__do_timed_wait(__lk, __clock_tp_ns::max());
} else {
__do_timed_wait(__lk, __clock_tp_ns(nanoseconds(__now_count_ns + __d_ns_count)));
}
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
@ -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

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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* {
auto __cleanup = [](void* __p) -> void* {
std::__destroy_at(static_cast<_Ep2*>(__p));
return __p;
};
# else
(void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) {
auto __cleanup = [](void* __p) { std::__destroy_at(static_cast<_Ep2*>(__p)); };
# endif
std::__destroy_at(static_cast<_Ep2*>(__p));
# ifdef __wasm__
return __p;
# endif
});
(void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast<std::type_info*>(&typeid(_Ep)), __cleanup);
try {
::new (__ex) _Ep2(__e);
@ -116,19 +115,48 @@ _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
# else
((void)__e);
std::abort();
# 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
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
class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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());
}
};

View file

@ -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) {

View file

@ -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);

View file

@ -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;
}

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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);
}
}

View file

@ -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

View file

@ -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

View 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
View 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

View 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
View 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

View file

@ -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;

View file

@ -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