diff options
Diffstat (limited to 'libstdc++-v3/include/bits')
79 files changed, 11192 insertions, 5015 deletions
diff --git a/libstdc++-v3/include/bits/align.h b/libstdc++-v3/include/bits/align.h index 2b40c37..6a85244 100644 --- a/libstdc++-v3/include/bits/align.h +++ b/libstdc++-v3/include/bits/align.h @@ -102,6 +102,23 @@ align(size_t __align, size_t __size, void*& __ptr, size_t& __space) noexcept } #endif // __glibcxx_assume_aligned +#ifdef __glibcxx_is_sufficiently_aligned // C++ >= 26 + /** @brief Is `__ptr` aligned to an _Align byte boundary? + * + * @tparam _Align An alignment value + * @tparam _Tp An object type + * + * C++26 20.2.5 [ptr.align] + * + * @ingroup memory + */ + template<size_t _Align, class _Tp> + [[nodiscard,__gnu__::__always_inline__]] + inline bool + is_sufficiently_aligned(_Tp* __ptr) + { return reinterpret_cast<__UINTPTR_TYPE__>(__ptr) % _Align == 0; } +#endif // __glibcxx_is_sufficiently_aligned + _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/include/bits/allocated_ptr.h b/libstdc++-v3/include/bits/allocated_ptr.h index 0b2b6fe..aa5355f 100644 --- a/libstdc++-v3/include/bits/allocated_ptr.h +++ b/libstdc++-v3/include/bits/allocated_ptr.h @@ -36,6 +36,7 @@ # include <type_traits> # include <bits/ptr_traits.h> # include <bits/alloc_traits.h> +# include <bits/utility.h> namespace std _GLIBCXX_VISIBILITY(default) { @@ -136,6 +137,101 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return { std::__allocate_guarded(__a) }; } + // An RAII type that acquires memory from an allocator. + // N.B. 'scoped' here in in the RAII sense, not the scoped allocator model, + // so this has nothing to do with `std::scoped_allocator_adaptor`. + // This class can be used to simplify the common pattern: + // + // auto ptr = alloc.allocate(1); + // try { + // std::construct_at(std::to_address(ptr), args); + // m_ptr = ptr; + // } catch (...) { + // alloc.deallocate(ptr, 1); + // throw; + // } + // + // Instead you can do: + // + // _Scoped_allocation sa(alloc); + // m_ptr = std::construct_at(sa.get(), args); + // (void) sa.release(); + // + // Or even simpler: + // + // _Scoped_allocation sa(alloc, std::in_place, args); + // m_ptr = sa.release(); + // + template<typename _Alloc> + struct _Scoped_allocation + { + using value_type = typename allocator_traits<_Alloc>::value_type; + using pointer = typename allocator_traits<_Alloc>::pointer; + + // Use `a` to allocate memory for `n` objects. + constexpr explicit + _Scoped_allocation(const _Alloc& __a, size_t __n = 1) + : _M_a(__a), _M_n(__n), _M_p(_M_a.allocate(__n)) + { } + +#if __glibcxx_optional >= 201606L + // Allocate memory for a single object and if that succeeds, + // construct an object using args. + // + // Does not do uses-allocator construction; don't use if you need that. + // + // CAUTION: the destructor will *not* destroy this object, it will only + // free the memory. That means the following pattern is unsafe: + // + // _Scoped_allocation sa(alloc, in_place, args); + // potentially_throwing_operations(); + // return sa.release(); + // + // If the middle operation throws, the object will not be destroyed. + template<typename... _Args> + constexpr explicit + _Scoped_allocation(const _Alloc& __a, in_place_t, _Args&&... __args) + : _Scoped_allocation(__a, 1) + { + // The target constructor has completed, so if the next line throws, + // the destructor will deallocate the memory. + allocator_traits<_Alloc>::construct(_M_a, get(), + std::forward<_Args>(__args)...); + } +#endif + + _GLIBCXX20_CONSTEXPR + ~_Scoped_allocation() + { + if (_M_p) [[__unlikely__]] + _M_a.deallocate(_M_p, _M_n); + } + + _Scoped_allocation(_Scoped_allocation&&) = delete; + + constexpr _Alloc + get_allocator() const noexcept { return _M_a; } + + constexpr value_type* + get() const noexcept + { return std::__to_address(_M_p); } + + [[__nodiscard__]] + constexpr pointer + release() noexcept { return std::__exchange(_M_p, nullptr); } + + private: + [[__no_unique_address__]] _Alloc _M_a; + size_t _M_n; + pointer _M_p; + }; + +#if __glibcxx_optional >= 201606L && __cpp_deduction_guides >= 201606L + template<typename _Alloc, typename... _Args> + _Scoped_allocation(_Alloc, in_place_t, _Args...) + -> _Scoped_allocation<_Alloc>; +#endif + /// @endcond _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h index 92d1269..90b8df5 100644 --- a/libstdc++-v3/include/bits/atomic_base.h +++ b/libstdc++-v3/include/bits/atomic_base.h @@ -1508,211 +1508,153 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; #undef _GLIBCXX20_INIT - template<typename _Tp, - bool = is_integral_v<_Tp> && !is_same_v<_Tp, bool>, - bool = is_floating_point_v<_Tp>> - struct __atomic_ref; + // __atomic_ref_base<const _Tp> provides the common APIs for const and + // non-const types, + // __atomic_ref_base<_Tp> inherits from __atomic_ref_base<const _Tp>, + // and provides the common APIs implementing constraints in [atomic.ref]. + // __atomic_ref<_Tp> inherits from __atomic_ref_base<_Tp> (const or non-const) + // adds type-specific mutating APIs. + // atomic_ref inherits from __atomic_ref; + + template<typename _Tp> + struct __atomic_ref_base; - // base class for non-integral, non-floating-point, non-pointer types template<typename _Tp> - struct __atomic_ref<_Tp, false, false> + struct __atomic_ref_base<const _Tp> { - static_assert(is_trivially_copyable_v<_Tp>); + private: + using _Vt = remove_cv_t<_Tp>; + + static consteval bool + _S_is_always_lock_free() + { + if constexpr (is_pointer_v<_Vt>) + return ATOMIC_POINTER_LOCK_FREE == 2; + else + return __atomic_always_lock_free(sizeof(_Vt), 0); + } - // 1/2/4/8/16-byte types must be aligned to at least their size. - static constexpr int _S_min_alignment - = (sizeof(_Tp) & (sizeof(_Tp) - 1)) || sizeof(_Tp) > 16 - ? 0 : sizeof(_Tp); + static consteval int + _S_required_alignment() + { + if constexpr (is_floating_point_v<_Vt> || is_pointer_v<_Vt>) + return __alignof__(_Vt); + else if constexpr ((sizeof(_Vt) & (sizeof(_Vt) - 1)) || sizeof(_Vt) > 16) + return alignof(_Vt); + else + // 1/2/4/8/16-byte types, including integral types, + // must be aligned to at least their size. + return (sizeof(_Vt) > alignof(_Vt)) ? sizeof(_Vt) : alignof(_Vt); + } public: - using value_type = _Tp; + using value_type = _Vt; + static_assert(is_trivially_copyable_v<value_type>); - static constexpr bool is_always_lock_free - = __atomic_always_lock_free(sizeof(_Tp), 0); + static constexpr bool is_always_lock_free = _S_is_always_lock_free(); + static_assert(is_always_lock_free || !is_volatile_v<_Tp>, + "atomic operations on volatile T must be lock-free"); - static constexpr size_t required_alignment - = _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp); + static constexpr size_t required_alignment = _S_required_alignment(); - __atomic_ref& operator=(const __atomic_ref&) = delete; + __atomic_ref_base() = delete; + __atomic_ref_base& operator=(const __atomic_ref_base&) = delete; explicit - __atomic_ref(_Tp& __t) : _M_ptr(std::__addressof(__t)) + __atomic_ref_base(const _Tp& __t) + : _M_ptr(const_cast<_Tp*>(std::addressof(__t))) { __glibcxx_assert(((__UINTPTR_TYPE__)_M_ptr % required_alignment) == 0); } - __atomic_ref(const __atomic_ref&) noexcept = default; - - _Tp - operator=(_Tp __t) const noexcept - { - this->store(__t); - return __t; - } + __atomic_ref_base(const __atomic_ref_base&) noexcept = default; - operator _Tp() const noexcept { return this->load(); } + operator value_type() const noexcept { return this->load(); } bool is_lock_free() const noexcept { return __atomic_impl::is_lock_free<sizeof(_Tp), required_alignment>(); } - void - store(_Tp __t, memory_order __m = memory_order_seq_cst) const noexcept - { __atomic_impl::store(_M_ptr, __t, __m); } - - _Tp + value_type load(memory_order __m = memory_order_seq_cst) const noexcept { return __atomic_impl::load(_M_ptr, __m); } - _Tp - exchange(_Tp __desired, memory_order __m = memory_order_seq_cst) - const noexcept - { return __atomic_impl::exchange(_M_ptr, __desired, __m); } - - bool - compare_exchange_weak(_Tp& __expected, _Tp __desired, - memory_order __success, - memory_order __failure) const noexcept - { - return __atomic_impl::compare_exchange_weak<true>( - _M_ptr, __expected, __desired, __success, __failure); - } - - bool - compare_exchange_strong(_Tp& __expected, _Tp __desired, - memory_order __success, - memory_order __failure) const noexcept - { - return __atomic_impl::compare_exchange_strong<true>( - _M_ptr, __expected, __desired, __success, __failure); - } - - bool - compare_exchange_weak(_Tp& __expected, _Tp __desired, - memory_order __order = memory_order_seq_cst) - const noexcept - { - return compare_exchange_weak(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - - bool - compare_exchange_strong(_Tp& __expected, _Tp __desired, - memory_order __order = memory_order_seq_cst) - const noexcept - { - return compare_exchange_strong(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - #if __glibcxx_atomic_wait _GLIBCXX_ALWAYS_INLINE void - wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept - { __atomic_impl::wait(_M_ptr, __old, __m); } - - // TODO add const volatile overload - - _GLIBCXX_ALWAYS_INLINE void - notify_one() const noexcept - { __atomic_impl::notify_one(_M_ptr); } - - // TODO add const volatile overload - - _GLIBCXX_ALWAYS_INLINE void - notify_all() const noexcept - { __atomic_impl::notify_all(_M_ptr); } - - // TODO add const volatile overload + wait(value_type __old, memory_order __m = memory_order_seq_cst) const noexcept + { + // TODO remove when volatile is supported + static_assert(!is_volatile_v<_Tp>, + "atomic waits on volatile are not supported"); + __atomic_impl::wait(_M_ptr, __old, __m); + } #endif // __glibcxx_atomic_wait - private: +#if __glibcxx_atomic_ref >= 202411L + _GLIBCXX_ALWAYS_INLINE constexpr const _Tp* + address() const noexcept + { return _M_ptr; } +#endif // __glibcxx_atomic_ref >= 202411L + + protected: _Tp* _M_ptr; }; - // base class for atomic_ref<integral-type> template<typename _Tp> - struct __atomic_ref<_Tp, true, false> + struct __atomic_ref_base + : __atomic_ref_base<const _Tp> { - static_assert(is_integral_v<_Tp>); - - public: - using value_type = _Tp; - using difference_type = value_type; - - static constexpr bool is_always_lock_free - = __atomic_always_lock_free(sizeof(_Tp), 0); - - static constexpr size_t required_alignment - = sizeof(_Tp) > alignof(_Tp) ? sizeof(_Tp) : alignof(_Tp); - - __atomic_ref() = delete; - __atomic_ref& operator=(const __atomic_ref&) = delete; + using value_type = typename __atomic_ref_base<const _Tp>::value_type; explicit - __atomic_ref(_Tp& __t) : _M_ptr(&__t) - { - __glibcxx_assert(((__UINTPTR_TYPE__)_M_ptr % required_alignment) == 0); - } - - __atomic_ref(const __atomic_ref&) noexcept = default; + __atomic_ref_base(_Tp& __t) : __atomic_ref_base<const _Tp>(__t) + { } - _Tp - operator=(_Tp __t) const noexcept + value_type + operator=(value_type __t) const noexcept { this->store(__t); return __t; } - operator _Tp() const noexcept { return this->load(); } - - bool - is_lock_free() const noexcept - { - return __atomic_impl::is_lock_free<sizeof(_Tp), required_alignment>(); - } - void - store(_Tp __t, memory_order __m = memory_order_seq_cst) const noexcept - { __atomic_impl::store(_M_ptr, __t, __m); } + store(value_type __t, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::store(this->_M_ptr, __t, __m); } - _Tp - load(memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::load(_M_ptr, __m); } - - _Tp - exchange(_Tp __desired, - memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::exchange(_M_ptr, __desired, __m); } + value_type + exchange(value_type __desired, memory_order __m = memory_order_seq_cst) + const noexcept + { return __atomic_impl::exchange(this->_M_ptr, __desired, __m); } bool - compare_exchange_weak(_Tp& __expected, _Tp __desired, + compare_exchange_weak(value_type& __expected, value_type __desired, memory_order __success, memory_order __failure) const noexcept { return __atomic_impl::compare_exchange_weak<true>( - _M_ptr, __expected, __desired, __success, __failure); + this->_M_ptr, __expected, __desired, __success, __failure); } bool - compare_exchange_strong(_Tp& __expected, _Tp __desired, - memory_order __success, - memory_order __failure) const noexcept + compare_exchange_strong(value_type& __expected, value_type __desired, + memory_order __success, + memory_order __failure) const noexcept { return __atomic_impl::compare_exchange_strong<true>( - _M_ptr, __expected, __desired, __success, __failure); + this->_M_ptr, __expected, __desired, __success, __failure); } bool - compare_exchange_weak(_Tp& __expected, _Tp __desired, + compare_exchange_weak(value_type& __expected, value_type __desired, memory_order __order = memory_order_seq_cst) const noexcept { return compare_exchange_weak(__expected, __desired, __order, - __cmpexch_failure_order(__order)); + __cmpexch_failure_order(__order)); } bool - compare_exchange_strong(_Tp& __expected, _Tp __desired, + compare_exchange_strong(value_type& __expected, value_type __desired, memory_order __order = memory_order_seq_cst) const noexcept { @@ -1722,48 +1664,88 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __glibcxx_atomic_wait _GLIBCXX_ALWAYS_INLINE void - wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept - { __atomic_impl::wait(_M_ptr, __old, __m); } - - // TODO add const volatile overload - - _GLIBCXX_ALWAYS_INLINE void notify_one() const noexcept - { __atomic_impl::notify_one(_M_ptr); } - - // TODO add const volatile overload + { + // TODO remove when volatile is supported + static_assert(!is_volatile_v<_Tp>, + "atomic waits on volatile are not supported"); + __atomic_impl::notify_one(this->_M_ptr); + } _GLIBCXX_ALWAYS_INLINE void notify_all() const noexcept - { __atomic_impl::notify_all(_M_ptr); } - - // TODO add const volatile overload + { + // TODO remove when volatile is supported + static_assert(!is_volatile_v<_Tp>, + "atomic waits on volatile are not supported"); + __atomic_impl::notify_all(this->_M_ptr); + } #endif // __glibcxx_atomic_wait +#if __glibcxx_atomic_ref >= 202411L + _GLIBCXX_ALWAYS_INLINE constexpr _Tp* + address() const noexcept + { return this->_M_ptr; } +#endif // __glibcxx_atomic_ref >= 202411L + }; + + template<typename _Tp, + bool = is_integral_v<_Tp> && !is_same_v<remove_cv_t<_Tp>, bool>, + bool = is_floating_point_v<_Tp>, + bool = is_pointer_v<_Tp>> + struct __atomic_ref; + + // base class for non-integral, non-floating-point, non-pointer types + template<typename _Tp> + struct __atomic_ref<_Tp, false, false, false> + : __atomic_ref_base<_Tp> + { + using __atomic_ref_base<_Tp>::__atomic_ref_base; + using __atomic_ref_base<_Tp>::operator=; + }; + + template<typename _Tp> + struct __atomic_ref<const _Tp, false, false, false> + : __atomic_ref_base<const _Tp> + { + using __atomic_ref_base<const _Tp>::__atomic_ref_base; + }; + + // base class for atomic_ref<integral-type> + template<typename _Tp> + struct __atomic_ref<_Tp, true, false, false> + : __atomic_ref_base<_Tp> + { + using value_type = typename __atomic_ref_base<_Tp>::value_type; + using difference_type = value_type; + + using __atomic_ref_base<_Tp>::__atomic_ref_base; + using __atomic_ref_base<_Tp>::operator=; + value_type fetch_add(value_type __i, memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::fetch_add(_M_ptr, __i, __m); } + { return __atomic_impl::fetch_add(this->_M_ptr, __i, __m); } value_type fetch_sub(value_type __i, memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::fetch_sub(_M_ptr, __i, __m); } + { return __atomic_impl::fetch_sub(this->_M_ptr, __i, __m); } value_type fetch_and(value_type __i, memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::fetch_and(_M_ptr, __i, __m); } + { return __atomic_impl::fetch_and(this->_M_ptr, __i, __m); } value_type fetch_or(value_type __i, memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::fetch_or(_M_ptr, __i, __m); } + { return __atomic_impl::fetch_or(this->_M_ptr, __i, __m); } value_type fetch_xor(value_type __i, memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::fetch_xor(_M_ptr, __i, __m); } + { return __atomic_impl::fetch_xor(this->_M_ptr, __i, __m); } _GLIBCXX_ALWAYS_INLINE value_type operator++(int) const noexcept @@ -1775,284 +1757,98 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION value_type operator++() const noexcept - { return __atomic_impl::__add_fetch(_M_ptr, value_type(1)); } + { return __atomic_impl::__add_fetch(this->_M_ptr, value_type(1)); } value_type operator--() const noexcept - { return __atomic_impl::__sub_fetch(_M_ptr, value_type(1)); } + { return __atomic_impl::__sub_fetch(this->_M_ptr, value_type(1)); } value_type operator+=(value_type __i) const noexcept - { return __atomic_impl::__add_fetch(_M_ptr, __i); } + { return __atomic_impl::__add_fetch(this->_M_ptr, __i); } value_type operator-=(value_type __i) const noexcept - { return __atomic_impl::__sub_fetch(_M_ptr, __i); } + { return __atomic_impl::__sub_fetch(this->_M_ptr, __i); } value_type operator&=(value_type __i) const noexcept - { return __atomic_impl::__and_fetch(_M_ptr, __i); } + { return __atomic_impl::__and_fetch(this->_M_ptr, __i); } value_type operator|=(value_type __i) const noexcept - { return __atomic_impl::__or_fetch(_M_ptr, __i); } + { return __atomic_impl::__or_fetch(this->_M_ptr, __i); } value_type operator^=(value_type __i) const noexcept - { return __atomic_impl::__xor_fetch(_M_ptr, __i); } + { return __atomic_impl::__xor_fetch(this->_M_ptr, __i); } + }; - private: - _Tp* _M_ptr; + template<typename _Tp> + struct __atomic_ref<const _Tp, true, false, false> + : __atomic_ref_base<const _Tp> + { + using difference_type = typename __atomic_ref_base<const _Tp>::value_type; + using __atomic_ref_base<const _Tp>::__atomic_ref_base; }; // base class for atomic_ref<floating-point-type> template<typename _Fp> - struct __atomic_ref<_Fp, false, true> + struct __atomic_ref<_Fp, false, true, false> + : __atomic_ref_base<_Fp> { - static_assert(is_floating_point_v<_Fp>); - - public: - using value_type = _Fp; + using value_type = typename __atomic_ref_base<_Fp>::value_type; using difference_type = value_type; - static constexpr bool is_always_lock_free - = __atomic_always_lock_free(sizeof(_Fp), 0); - - static constexpr size_t required_alignment = __alignof__(_Fp); - - __atomic_ref() = delete; - __atomic_ref& operator=(const __atomic_ref&) = delete; - - explicit - __atomic_ref(_Fp& __t) : _M_ptr(&__t) - { - __glibcxx_assert(((__UINTPTR_TYPE__)_M_ptr % required_alignment) == 0); - } - - __atomic_ref(const __atomic_ref&) noexcept = default; - - _Fp - operator=(_Fp __t) const noexcept - { - this->store(__t); - return __t; - } - - operator _Fp() const noexcept { return this->load(); } - - bool - is_lock_free() const noexcept - { - return __atomic_impl::is_lock_free<sizeof(_Fp), required_alignment>(); - } - - void - store(_Fp __t, memory_order __m = memory_order_seq_cst) const noexcept - { __atomic_impl::store(_M_ptr, __t, __m); } - - _Fp - load(memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::load(_M_ptr, __m); } - - _Fp - exchange(_Fp __desired, - memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::exchange(_M_ptr, __desired, __m); } - - bool - compare_exchange_weak(_Fp& __expected, _Fp __desired, - memory_order __success, - memory_order __failure) const noexcept - { - return __atomic_impl::compare_exchange_weak<true>( - _M_ptr, __expected, __desired, __success, __failure); - } - - bool - compare_exchange_strong(_Fp& __expected, _Fp __desired, - memory_order __success, - memory_order __failure) const noexcept - { - return __atomic_impl::compare_exchange_strong<true>( - _M_ptr, __expected, __desired, __success, __failure); - } - - bool - compare_exchange_weak(_Fp& __expected, _Fp __desired, - memory_order __order = memory_order_seq_cst) - const noexcept - { - return compare_exchange_weak(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - - bool - compare_exchange_strong(_Fp& __expected, _Fp __desired, - memory_order __order = memory_order_seq_cst) - const noexcept - { - return compare_exchange_strong(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - -#if __glibcxx_atomic_wait - _GLIBCXX_ALWAYS_INLINE void - wait(_Fp __old, memory_order __m = memory_order_seq_cst) const noexcept - { __atomic_impl::wait(_M_ptr, __old, __m); } - - // TODO add const volatile overload - - _GLIBCXX_ALWAYS_INLINE void - notify_one() const noexcept - { __atomic_impl::notify_one(_M_ptr); } - - // TODO add const volatile overload - - _GLIBCXX_ALWAYS_INLINE void - notify_all() const noexcept - { __atomic_impl::notify_all(_M_ptr); } - - // TODO add const volatile overload -#endif // __glibcxx_atomic_wait + using __atomic_ref_base<_Fp>::__atomic_ref_base; + using __atomic_ref_base<_Fp>::operator=; value_type fetch_add(value_type __i, memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::__fetch_add_flt(_M_ptr, __i, __m); } + { return __atomic_impl::__fetch_add_flt(this->_M_ptr, __i, __m); } value_type fetch_sub(value_type __i, memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::__fetch_sub_flt(_M_ptr, __i, __m); } + { return __atomic_impl::__fetch_sub_flt(this->_M_ptr, __i, __m); } value_type operator+=(value_type __i) const noexcept - { return __atomic_impl::__add_fetch_flt(_M_ptr, __i); } + { return __atomic_impl::__add_fetch_flt(this->_M_ptr, __i); } value_type operator-=(value_type __i) const noexcept - { return __atomic_impl::__sub_fetch_flt(_M_ptr, __i); } + { return __atomic_impl::__sub_fetch_flt(this->_M_ptr, __i); } + }; - private: - _Fp* _M_ptr; + template<typename _Fp> + struct __atomic_ref<const _Fp, false, true, false> + : __atomic_ref_base<const _Fp> + { + using difference_type = typename __atomic_ref_base<const _Fp>::value_type; + using __atomic_ref_base<const _Fp>::__atomic_ref_base; }; // base class for atomic_ref<pointer-type> - template<typename _Tp> - struct __atomic_ref<_Tp*, false, false> + template<typename _Pt> + struct __atomic_ref<_Pt, false, false, true> + : __atomic_ref_base<_Pt> { - public: - using value_type = _Tp*; + using value_type = typename __atomic_ref_base<_Pt>::value_type; using difference_type = ptrdiff_t; - static constexpr bool is_always_lock_free = ATOMIC_POINTER_LOCK_FREE == 2; - - static constexpr size_t required_alignment = __alignof__(_Tp*); - - __atomic_ref() = delete; - __atomic_ref& operator=(const __atomic_ref&) = delete; - - explicit - __atomic_ref(_Tp*& __t) : _M_ptr(std::__addressof(__t)) - { - __glibcxx_assert(((__UINTPTR_TYPE__)_M_ptr % required_alignment) == 0); - } - - __atomic_ref(const __atomic_ref&) noexcept = default; - - _Tp* - operator=(_Tp* __t) const noexcept - { - this->store(__t); - return __t; - } - - operator _Tp*() const noexcept { return this->load(); } - - bool - is_lock_free() const noexcept - { - return __atomic_impl::is_lock_free<sizeof(_Tp*), required_alignment>(); - } - - void - store(_Tp* __t, memory_order __m = memory_order_seq_cst) const noexcept - { __atomic_impl::store(_M_ptr, __t, __m); } - - _Tp* - load(memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::load(_M_ptr, __m); } - - _Tp* - exchange(_Tp* __desired, - memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::exchange(_M_ptr, __desired, __m); } - - bool - compare_exchange_weak(_Tp*& __expected, _Tp* __desired, - memory_order __success, - memory_order __failure) const noexcept - { - return __atomic_impl::compare_exchange_weak<true>( - _M_ptr, __expected, __desired, __success, __failure); - } - - bool - compare_exchange_strong(_Tp*& __expected, _Tp* __desired, - memory_order __success, - memory_order __failure) const noexcept - { - return __atomic_impl::compare_exchange_strong<true>( - _M_ptr, __expected, __desired, __success, __failure); - } - - bool - compare_exchange_weak(_Tp*& __expected, _Tp* __desired, - memory_order __order = memory_order_seq_cst) - const noexcept - { - return compare_exchange_weak(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - - bool - compare_exchange_strong(_Tp*& __expected, _Tp* __desired, - memory_order __order = memory_order_seq_cst) - const noexcept - { - return compare_exchange_strong(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - -#if __glibcxx_atomic_wait - _GLIBCXX_ALWAYS_INLINE void - wait(_Tp* __old, memory_order __m = memory_order_seq_cst) const noexcept - { __atomic_impl::wait(_M_ptr, __old, __m); } - - // TODO add const volatile overload - - _GLIBCXX_ALWAYS_INLINE void - notify_one() const noexcept - { __atomic_impl::notify_one(_M_ptr); } - - // TODO add const volatile overload - - _GLIBCXX_ALWAYS_INLINE void - notify_all() const noexcept - { __atomic_impl::notify_all(_M_ptr); } - - // TODO add const volatile overload -#endif // __glibcxx_atomic_wait - + using __atomic_ref_base<_Pt>::__atomic_ref_base; + using __atomic_ref_base<_Pt>::operator=; _GLIBCXX_ALWAYS_INLINE value_type fetch_add(difference_type __d, memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::fetch_add(_M_ptr, _S_type_size(__d), __m); } + { return __atomic_impl::fetch_add(this->_M_ptr, _S_type_size(__d), __m); } _GLIBCXX_ALWAYS_INLINE value_type fetch_sub(difference_type __d, memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::fetch_sub(_M_ptr, _S_type_size(__d), __m); } + { return __atomic_impl::fetch_sub(this->_M_ptr, _S_type_size(__d), __m); } value_type operator++(int) const noexcept @@ -2065,36 +1861,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION value_type operator++() const noexcept { - return __atomic_impl::__add_fetch(_M_ptr, _S_type_size(1)); + return __atomic_impl::__add_fetch(this->_M_ptr, _S_type_size(1)); } value_type operator--() const noexcept { - return __atomic_impl::__sub_fetch(_M_ptr, _S_type_size(1)); + return __atomic_impl::__sub_fetch(this->_M_ptr, _S_type_size(1)); } value_type operator+=(difference_type __d) const noexcept { - return __atomic_impl::__add_fetch(_M_ptr, _S_type_size(__d)); + return __atomic_impl::__add_fetch(this->_M_ptr, _S_type_size(__d)); } value_type operator-=(difference_type __d) const noexcept { - return __atomic_impl::__sub_fetch(_M_ptr, _S_type_size(__d)); + return __atomic_impl::__sub_fetch(this->_M_ptr, _S_type_size(__d)); } private: static constexpr ptrdiff_t _S_type_size(ptrdiff_t __d) noexcept { - static_assert(is_object_v<_Tp>); - return __d * sizeof(_Tp); + using _Et = remove_pointer_t<value_type>; + static_assert(is_object_v<_Et>); + return __d * sizeof(_Et); } + }; - _Tp** _M_ptr; + template<typename _Pt> + struct __atomic_ref<const _Pt, false, false, true> + : __atomic_ref_base<const _Pt> + { + using difference_type = ptrdiff_t; + using __atomic_ref_base<const _Pt>::__atomic_ref_base; }; #endif // C++2a diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h b/libstdc++-v3/include/bits/atomic_timed_wait.h index 9a6ac95..3c3aa2c 100644 --- a/libstdc++-v3/include/bits/atomic_timed_wait.h +++ b/libstdc++-v3/include/bits/atomic_timed_wait.h @@ -37,7 +37,6 @@ #include <bits/atomic_wait.h> #if __glibcxx_atomic_wait -#include <bits/functional_hash.h> #include <bits/this_thread_sleep.h> #include <bits/chrono.h> @@ -70,383 +69,162 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Dur>& __atime) noexcept { using __w_dur = typename __wait_clock_t::duration; - return chrono::ceil<__w_dur>(__atime); - } - -#ifdef _GLIBCXX_HAVE_LINUX_FUTEX -#define _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT - // returns true if wait ended before timeout - template<typename _Dur> - bool - __platform_wait_until_impl(const __platform_wait_t* __addr, - __platform_wait_t __old, - const chrono::time_point<__wait_clock_t, _Dur>& - __atime) noexcept - { - auto __s = chrono::time_point_cast<chrono::seconds>(__atime); - auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s); - - struct timespec __rt = - { - static_cast<std::time_t>(__s.time_since_epoch().count()), - static_cast<long>(__ns.count()) - }; - - auto __e = syscall (SYS_futex, __addr, - static_cast<int>(__futex_wait_flags:: - __wait_bitset_private), - __old, &__rt, nullptr, - static_cast<int>(__futex_wait_flags:: - __bitset_match_any)); - - if (__e) - { - if (errno == ETIMEDOUT) - return false; - if (errno != EINTR && errno != EAGAIN) - __throw_system_error(errno); - } - return true; - } - - // returns true if wait ended before timeout - template<typename _Clock, typename _Dur> - bool - __platform_wait_until(const __platform_wait_t* __addr, __platform_wait_t __old, - const chrono::time_point<_Clock, _Dur>& __atime) - { - if constexpr (is_same_v<__wait_clock_t, _Clock>) - { - return __platform_wait_until_impl(__addr, __old, __atime); - } + if constexpr (is_same_v<__w_dur, _Dur>) + return __atime; else - { - if (!__platform_wait_until_impl(__addr, __old, - __to_wait_clock(__atime))) - { - // We got a timeout when measured against __clock_t but - // we need to check against the caller-supplied clock - // to tell whether we should return a timeout. - if (_Clock::now() < __atime) - return true; - } - return false; - } + return chrono::ceil<__w_dur>(__atime); } -#else -// define _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT and implement __platform_wait_until() -// if there is a more efficient primitive supported by the platform -// (e.g. __ulock_wait())which is better than pthread_cond_clockwait -#endif // ! PLATFORM_TIMED_WAIT - -#ifdef _GLIBCXX_HAS_GTHREADS - // Returns true if wait ended before timeout. - // _Clock must be either steady_clock or system_clock. - template<typename _Clock, typename _Dur> - bool - __cond_wait_until_impl(__condvar& __cv, mutex& __mx, - const chrono::time_point<_Clock, _Dur>& __atime) - { - static_assert(std::__is_one_of<_Clock, chrono::steady_clock, - chrono::system_clock>::value); - - auto __s = chrono::time_point_cast<chrono::seconds>(__atime); - auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s); - __gthread_time_t __ts = - { - static_cast<std::time_t>(__s.time_since_epoch().count()), - static_cast<long>(__ns.count()) - }; + // This uses a nanoseconds duration for the timeout argument. + // For __abi_version=0 that is the time since the steady_clock's epoch. + // It's possible that in future we will add new __wait_flags constants + // to indicate that the timeout is the time since the system_clock epoch, + // or is a relative timeout not an absolute time. + __wait_result_type + __wait_until_impl(const void* __addr, __wait_args_base& __args, + const chrono::nanoseconds& __timeout); -#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT - if constexpr (is_same_v<chrono::steady_clock, _Clock>) - __cv.wait_until(__mx, CLOCK_MONOTONIC, __ts); - else -#endif - __cv.wait_until(__mx, __ts); - return _Clock::now() < __atime; - } - - // returns true if wait ended before timeout template<typename _Clock, typename _Dur> - bool - __cond_wait_until(__condvar& __cv, mutex& __mx, - const chrono::time_point<_Clock, _Dur>& __atime) + __wait_result_type + __wait_until(const void* __addr, __wait_args_base& __args, + const chrono::time_point<_Clock, _Dur>& __atime) noexcept { -#ifdef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT - if constexpr (is_same_v<_Clock, chrono::steady_clock>) - return __detail::__cond_wait_until_impl(__cv, __mx, __atime); - else -#endif - if constexpr (is_same_v<_Clock, chrono::system_clock>) - return __detail::__cond_wait_until_impl(__cv, __mx, __atime); - else - { - if (__cond_wait_until_impl(__cv, __mx, - __to_wait_clock(__atime))) - { - // We got a timeout when measured against __clock_t but - // we need to check against the caller-supplied clock - // to tell whether we should return a timeout. - if (_Clock::now() < __atime) - return true; - } - return false; - } - } -#endif // _GLIBCXX_HAS_GTHREADS + auto __at = __detail::__to_wait_clock(__atime); + auto __res = __detail::__wait_until_impl(__addr, __args, + __at.time_since_epoch()); - struct __timed_waiter_pool : __waiter_pool_base - { - // returns true if wait ended before timeout - template<typename _Clock, typename _Dur> - bool - _M_do_wait_until(__platform_wait_t* __addr, __platform_wait_t __old, - const chrono::time_point<_Clock, _Dur>& __atime) - { -#ifdef _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT - return __platform_wait_until(__addr, __old, __atime); -#else - __platform_wait_t __val; - __atomic_load(__addr, &__val, __ATOMIC_RELAXED); - if (__val == __old) + if constexpr (!is_same_v<__wait_clock_t, _Clock>) + if (__res._M_timeout) { - lock_guard<mutex> __l(_M_mtx); - return __cond_wait_until(_M_cv, _M_mtx, __atime); + // We got a timeout when measured against __clock_t but + // we need to check against the caller-supplied clock + // to tell whether we should return a timeout. + if (_Clock::now() < __atime) + __res._M_timeout = false; } - else - return true; -#endif // _GLIBCXX_HAVE_PLATFORM_TIMED_WAIT - } - }; - - struct __timed_backoff_spin_policy - { - __wait_clock_t::time_point _M_deadline; - __wait_clock_t::time_point _M_t0; - - template<typename _Clock, typename _Dur> - __timed_backoff_spin_policy(chrono::time_point<_Clock, _Dur> - __deadline = _Clock::time_point::max(), - chrono::time_point<_Clock, _Dur> - __t0 = _Clock::now()) noexcept - : _M_deadline(__to_wait_clock(__deadline)) - , _M_t0(__to_wait_clock(__t0)) - { } - - bool - operator()() const noexcept - { - using namespace literals::chrono_literals; - auto __now = __wait_clock_t::now(); - if (_M_deadline <= __now) - return false; - - // FIXME: this_thread::sleep_for not available #ifdef _GLIBCXX_NO_SLEEP - - auto __elapsed = __now - _M_t0; - if (__elapsed > 128ms) - { - this_thread::sleep_for(64ms); - } - else if (__elapsed > 64us) - { - this_thread::sleep_for(__elapsed / 2); - } - else if (__elapsed > 4us) - { - __thread_yield(); - } - else - return false; - return true; + return __res; } - }; - template<typename _EntersWait> - struct __timed_waiter : __waiter_base<__timed_waiter_pool> + template<typename _Rep, typename _Period> + __wait_result_type + __wait_for(const void* __addr, __wait_args_base& __args, + const chrono::duration<_Rep, _Period>& __rtime) noexcept { - using __base_type = __waiter_base<__timed_waiter_pool>; - - template<typename _Tp> - __timed_waiter(const _Tp* __addr) noexcept - : __base_type(__addr) - { - if constexpr (_EntersWait::value) - _M_w._M_enter_wait(); - } - - ~__timed_waiter() - { - if constexpr (_EntersWait::value) - _M_w._M_leave_wait(); - } - - // returns true if wait ended before timeout - template<typename _Tp, typename _ValFn, - typename _Clock, typename _Dur> - bool - _M_do_wait_until_v(_Tp __old, _ValFn __vfn, - const chrono::time_point<_Clock, _Dur>& - __atime) noexcept - { - __platform_wait_t __val; - if (_M_do_spin(__old, std::move(__vfn), __val, - __timed_backoff_spin_policy(__atime))) - return true; - return __base_type::_M_w._M_do_wait_until(__base_type::_M_addr, __val, __atime); - } - - // returns true if wait ended before timeout - template<typename _Pred, - typename _Clock, typename _Dur> - bool - _M_do_wait_until(_Pred __pred, __platform_wait_t __val, - const chrono::time_point<_Clock, _Dur>& - __atime) noexcept - { - for (auto __now = _Clock::now(); __now < __atime; - __now = _Clock::now()) - { - if (__base_type::_M_w._M_do_wait_until( - __base_type::_M_addr, __val, __atime) - && __pred()) - return true; - - if (__base_type::_M_do_spin(__pred, __val, - __timed_backoff_spin_policy(__atime, __now))) - return true; - } - return false; - } - - // returns true if wait ended before timeout - template<typename _Pred, - typename _Clock, typename _Dur> - bool - _M_do_wait_until(_Pred __pred, - const chrono::time_point<_Clock, _Dur>& - __atime) noexcept + if (!__rtime.count()) { - __platform_wait_t __val; - if (__base_type::_M_do_spin(__pred, __val, - __timed_backoff_spin_policy(__atime))) - return true; - return _M_do_wait_until(__pred, __val, __atime); - } - - template<typename _Tp, typename _ValFn, - typename _Rep, typename _Period> - bool - _M_do_wait_for_v(_Tp __old, _ValFn __vfn, - const chrono::duration<_Rep, _Period>& - __rtime) noexcept - { - __platform_wait_t __val; - if (_M_do_spin_v(__old, std::move(__vfn), __val)) - return true; - - if (!__rtime.count()) - return false; // no rtime supplied, and spin did not acquire - - auto __reltime = chrono::ceil<__wait_clock_t::duration>(__rtime); - - return __base_type::_M_w._M_do_wait_until( - __base_type::_M_addr, - __val, - chrono::steady_clock::now() + __reltime); + // no rtime supplied, just spin a bit + __args._M_flags |= __wait_flags::__do_spin | __wait_flags::__spin_only; + return __detail::__wait_impl(__addr, __args); } - template<typename _Pred, - typename _Rep, typename _Period> - bool - _M_do_wait_for(_Pred __pred, - const chrono::duration<_Rep, _Period>& __rtime) noexcept - { - __platform_wait_t __val; - if (__base_type::_M_do_spin(__pred, __val)) - return true; - - if (!__rtime.count()) - return false; // no rtime supplied, and spin did not acquire - - auto __reltime = chrono::ceil<__wait_clock_t::duration>(__rtime); - - return _M_do_wait_until(__pred, __val, - chrono::steady_clock::now() + __reltime); - } - }; - - using __enters_timed_wait = __timed_waiter<std::true_type>; - using __bare_timed_wait = __timed_waiter<std::false_type>; + auto const __reltime = chrono::ceil<__wait_clock_t::duration>(__rtime); + auto const __atime = chrono::steady_clock::now() + __reltime; + return __detail::__wait_until(__addr, __args, __atime); + } } // namespace __detail // returns true if wait ended before timeout - template<typename _Tp, typename _ValFn, + template<typename _Tp, + typename _Pred, typename _ValFn, typename _Clock, typename _Dur> bool - __atomic_wait_address_until_v(const _Tp* __addr, _Tp&& __old, _ValFn&& __vfn, - const chrono::time_point<_Clock, _Dur>& - __atime) noexcept + __atomic_wait_address_until(const _Tp* __addr, _Pred&& __pred, + _ValFn&& __vfn, + const chrono::time_point<_Clock, _Dur>& __atime, + bool __bare_wait = false) noexcept { - __detail::__enters_timed_wait __w{__addr}; - return __w._M_do_wait_until_v(__old, __vfn, __atime); + __detail::__wait_args __args{ __addr, __bare_wait }; + _Tp __val = __args._M_setup_wait(__addr, __vfn); + while (!__pred(__val)) + { + auto __res = __detail::__wait_until(__addr, __args, __atime); + if (__res._M_timeout) + return false; // C++26 will also return last observed __val + __val = __args._M_setup_wait(__addr, __vfn, __res); + } + return true; // C++26 will also return last observed __val } - template<typename _Tp, typename _Pred, - typename _Clock, typename _Dur> + template<typename _Clock, typename _Dur> bool - __atomic_wait_address_until(const _Tp* __addr, _Pred __pred, - const chrono::time_point<_Clock, _Dur>& - __atime) noexcept + __atomic_wait_address_until_v(const __detail::__platform_wait_t* __addr, + __detail::__platform_wait_t __old, + int __order, + const chrono::time_point<_Clock, _Dur>& __atime, + bool __bare_wait = false) noexcept { - __detail::__enters_timed_wait __w{__addr}; - return __w._M_do_wait_until(__pred, __atime); + // This function must not be used if __wait_impl might use a proxy wait: + __glibcxx_assert(__platform_wait_uses_type<__detail::__platform_wait_t>); + + __detail::__wait_args __args{ __addr, __old, __order, __bare_wait }; + auto __res = __detail::__wait_until(__addr, __args, __atime); + return !__res._M_timeout; // C++26 will also return last observed __val } - template<typename _Pred, + template<typename _Tp, typename _ValFn, typename _Clock, typename _Dur> bool - __atomic_wait_address_until_bare(const __detail::__platform_wait_t* __addr, - _Pred __pred, - const chrono::time_point<_Clock, _Dur>& - __atime) noexcept + __atomic_wait_address_until_v(const _Tp* __addr, _Tp&& __old, + _ValFn&& __vfn, + const chrono::time_point<_Clock, _Dur>& __atime, + bool __bare_wait = false) noexcept { - __detail::__bare_timed_wait __w{__addr}; - return __w._M_do_wait_until(__pred, __atime); + auto __pfn = [&](const _Tp& __val) { + return !__detail::__atomic_eq(__old, __val); + }; + return std::__atomic_wait_address_until(__addr, __pfn, __vfn, __atime, + __bare_wait); } - template<typename _Tp, typename _ValFn, + template<typename _Tp, + typename _Pred, typename _ValFn, typename _Rep, typename _Period> bool - __atomic_wait_address_for_v(const _Tp* __addr, _Tp&& __old, _ValFn&& __vfn, - const chrono::duration<_Rep, _Period>& __rtime) noexcept + __atomic_wait_address_for(const _Tp* __addr, _Pred&& __pred, + _ValFn&& __vfn, + const chrono::duration<_Rep, _Period>& __rtime, + bool __bare_wait = false) noexcept { - __detail::__enters_timed_wait __w{__addr}; - return __w._M_do_wait_for_v(__old, __vfn, __rtime); + __detail::__wait_args __args{ __addr, __bare_wait }; + _Tp __val = __args._M_setup_wait(__addr, __vfn); + while (!__pred(__val)) + { + auto __res = __detail::__wait_for(__addr, __args, __rtime); + if (__res._M_timeout) + return false; // C++26 will also return last observed __val + __val = __args._M_setup_wait(__addr, __vfn); + } + return true; // C++26 will also return last observed __val } - template<typename _Tp, typename _Pred, - typename _Rep, typename _Period> + template<typename _Rep, typename _Period> bool - __atomic_wait_address_for(const _Tp* __addr, _Pred __pred, - const chrono::duration<_Rep, _Period>& __rtime) noexcept + __atomic_wait_address_for_v(const __detail::__platform_wait_t* __addr, + __detail::__platform_wait_t __old, + int __order, + const chrono::duration<_Rep, _Period>& __rtime, + bool __bare_wait = false) noexcept { + // This function must not be used if __wait_impl might use a proxy wait: + __glibcxx_assert(__platform_wait_uses_type<__detail::__platform_wait_t>); - __detail::__enters_timed_wait __w{__addr}; - return __w._M_do_wait_for(__pred, __rtime); + __detail::__wait_args __args{ __addr, __old, __order, __bare_wait }; + auto __res = __detail::__wait_for(__addr, __args, __rtime); + return !__res._M_timeout; // C++26 will also return last observed __val } - template<typename _Pred, + template<typename _Tp, typename _ValFn, typename _Rep, typename _Period> bool - __atomic_wait_address_for_bare(const __detail::__platform_wait_t* __addr, - _Pred __pred, - const chrono::duration<_Rep, _Period>& __rtime) noexcept + __atomic_wait_address_for_v(const _Tp* __addr, _Tp&& __old, _ValFn&& __vfn, + const chrono::duration<_Rep, _Period>& __rtime, + bool __bare_wait = false) noexcept { - __detail::__bare_timed_wait __w{__addr}; - return __w._M_do_wait_for(__pred, __rtime); + auto __pfn = [&](const _Tp& __val) { + return !__detail::__atomic_eq(__old, __val); + }; + return __atomic_wait_address_for(__addr, __pfn, forward<_ValFn>(__vfn), + __rtime, __bare_wait); } _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/atomic_wait.h b/libstdc++-v3/include/bits/atomic_wait.h index 6d1554f..84b8b4c 100644 --- a/libstdc++-v3/include/bits/atomic_wait.h +++ b/libstdc++-v3/include/bits/atomic_wait.h @@ -37,104 +37,68 @@ #include <bits/version.h> #if __glibcxx_atomic_wait -#include <cstdint> -#include <bits/functional_hash.h> #include <bits/gthr.h> #include <ext/numeric_traits.h> -#ifdef _GLIBCXX_HAVE_LINUX_FUTEX -# include <cerrno> -# include <climits> -# include <unistd.h> -# include <syscall.h> -# include <bits/functexcept.h> -#endif - -# include <bits/std_mutex.h> // std::mutex, std::__condvar +#include <bits/stl_pair.h> namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace __detail { -#ifdef _GLIBCXX_HAVE_LINUX_FUTEX -#define _GLIBCXX_HAVE_PLATFORM_WAIT 1 + // TODO: this needs to be false for types with padding, e.g. __int20. + // TODO: should this be true only for integral, enum, and pointer types? + template<typename _Tp> + concept __waitable + = is_scalar_v<_Tp> && __builtin_popcountg(sizeof(_Tp)) == 1 + && (sizeof(_Tp) <= sizeof(__UINT64_TYPE__)); + } + +#if defined _GLIBCXX_HAVE_LINUX_FUTEX + namespace __detail + { + // Use futex syscall on int objects. using __platform_wait_t = int; inline constexpr size_t __platform_wait_alignment = 4; + } + // Defined to true for a subset of __waitable types which are statically + // known to definitely be able to use futex, not a proxy wait. + template<typename _Tp> + inline constexpr bool __platform_wait_uses_type + = __detail::__waitable<_Tp> + && sizeof(_Tp) == sizeof(int) && alignof(_Tp) >= 4; #else // define _GLIBCX_HAVE_PLATFORM_WAIT and implement __platform_wait() // and __platform_notify() if there is a more efficient primitive supported // by the platform (e.g. __ulock_wait()/__ulock_wake()) which is better than // a mutex/condvar based wait. + namespace __detail + { # if ATOMIC_LONG_LOCK_FREE == 2 using __platform_wait_t = unsigned long; # else using __platform_wait_t = unsigned int; # endif inline constexpr size_t __platform_wait_alignment - = __alignof__(__platform_wait_t); -#endif + = sizeof(__platform_wait_t) < __alignof__(__platform_wait_t) + ? __alignof__(__platform_wait_t) : sizeof(__platform_wait_t); } // namespace __detail - template<typename _Tp> - inline constexpr bool __platform_wait_uses_type -#ifdef _GLIBCXX_HAVE_PLATFORM_WAIT - = is_scalar_v<_Tp> - && ((sizeof(_Tp) == sizeof(__detail::__platform_wait_t)) - && (alignof(_Tp*) >= __detail::__platform_wait_alignment)); -#else - = false; + // This must be false for the general case where we don't know of any + // futex-like syscall. + template<typename> + inline constexpr bool __platform_wait_uses_type = false; #endif namespace __detail { -#ifdef _GLIBCXX_HAVE_LINUX_FUTEX - enum class __futex_wait_flags : int - { -#ifdef _GLIBCXX_HAVE_LINUX_FUTEX_PRIVATE - __private_flag = 128, -#else - __private_flag = 0, -#endif - __wait = 0, - __wake = 1, - __wait_bitset = 9, - __wake_bitset = 10, - __wait_private = __wait | __private_flag, - __wake_private = __wake | __private_flag, - __wait_bitset_private = __wait_bitset | __private_flag, - __wake_bitset_private = __wake_bitset | __private_flag, - __bitset_match_any = -1 - }; - - template<typename _Tp> - void - __platform_wait(const _Tp* __addr, __platform_wait_t __val) noexcept - { - auto __e = syscall (SYS_futex, static_cast<const void*>(__addr), - static_cast<int>(__futex_wait_flags::__wait_private), - __val, nullptr); - if (!__e || errno == EAGAIN) - return; - if (errno != EINTR) - __throw_system_error(errno); - } - - template<typename _Tp> - void - __platform_notify(const _Tp* __addr, bool __all) noexcept - { - syscall (SYS_futex, static_cast<const void*>(__addr), - static_cast<int>(__futex_wait_flags::__wake_private), - __all ? INT_MAX : 1); - } -#endif - inline void __thread_yield() noexcept { #if defined _GLIBCXX_HAS_GTHREADS && defined _GLIBCXX_USE_SCHED_YIELD - __gthread_yield(); + __gthread_yield(); #endif } @@ -148,334 +112,233 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif } - inline constexpr auto __atomic_spin_count_relax = 12; - inline constexpr auto __atomic_spin_count = 16; - - struct __default_spin_policy - { - bool - operator()() const noexcept - { return false; } - }; - - template<typename _Pred, - typename _Spin = __default_spin_policy> - bool - __atomic_spin(_Pred& __pred, _Spin __spin = _Spin{ }) noexcept - { - for (auto __i = 0; __i < __atomic_spin_count; ++__i) - { - if (__pred()) - return true; - - if (__i < __atomic_spin_count_relax) - __detail::__thread_relax(); - else - __detail::__thread_yield(); - } - - while (__spin()) - { - if (__pred()) - return true; - } - - return false; - } - // return true if equal template<typename _Tp> - bool __atomic_compare(const _Tp& __a, const _Tp& __b) + inline bool + __atomic_eq(const _Tp& __a, const _Tp& __b) { // TODO make this do the correct padding bit ignoring comparison - return __builtin_memcmp(&__a, &__b, sizeof(_Tp)) == 0; + return __builtin_memcmp(std::addressof(__a), std::addressof(__b), + sizeof(_Tp)) == 0; } - struct __waiter_pool_base - { - // Don't use std::hardware_destructive_interference_size here because we - // don't want the layout of library types to depend on compiler options. - static constexpr auto _S_align = 64; - - alignas(_S_align) __platform_wait_t _M_wait = 0; + // Storage for up to 64 bits of value, should be considered opaque bits. + using __wait_value_type = __UINT64_TYPE__; -#ifndef _GLIBCXX_HAVE_PLATFORM_WAIT - mutex _M_mtx; -#endif - - alignas(_S_align) __platform_wait_t _M_ver = 0; + // lightweight std::optional<__wait_value_type> + struct __wait_result_type + { + __wait_value_type _M_val; + unsigned char _M_has_val : 1; // _M_val value was loaded before return. + unsigned char _M_timeout : 1; // Waiting function ended with timeout. + unsigned char _M_unused : 6; // padding + }; -#ifndef _GLIBCXX_HAVE_PLATFORM_WAIT - __condvar _M_cv; -#endif - __waiter_pool_base() = default; + enum class __wait_flags : __UINT_LEAST32_TYPE__ + { + __abi_version = 0x00000000, + // currently unused = 1, + __track_contention = 2, + __do_spin = 4, + __spin_only = 8, // Ignored unless __do_spin is also set. + // __abi_version_mask = 0xff000000, + }; - void - _M_enter_wait() noexcept - { __atomic_fetch_add(&_M_wait, 1, __ATOMIC_SEQ_CST); } + [[__gnu__::__always_inline__]] + constexpr __wait_flags + operator|(__wait_flags __l, __wait_flags __r) noexcept + { + using _Ut = underlying_type_t<__wait_flags>; + return static_cast<__wait_flags>(static_cast<_Ut>(__l) + | static_cast<_Ut>(__r)); + } - void - _M_leave_wait() noexcept - { __atomic_fetch_sub(&_M_wait, 1, __ATOMIC_RELEASE); } + [[__gnu__::__always_inline__]] + constexpr __wait_flags& + operator|=(__wait_flags& __l, __wait_flags __r) noexcept + { return __l = __l | __r; } + // Simple aggregate containing arguments used by implementation details. + struct __wait_args_base + { + __wait_flags _M_flags; + int _M_order = __ATOMIC_ACQUIRE; + __wait_value_type _M_old = 0; + void* _M_wait_state = nullptr; + const void* _M_obj = nullptr; // The address of the object to wait on. + unsigned char _M_obj_size = 0; // The size of that object. + + // Test whether _M_flags & __flags is non-zero. bool - _M_waiting() const noexcept + operator&(__wait_flags __flags) const noexcept { - __platform_wait_t __res; - __atomic_load(&_M_wait, &__res, __ATOMIC_SEQ_CST); - return __res != 0; + using _Ut = underlying_type_t<__wait_flags>; + return static_cast<_Ut>(_M_flags) & static_cast<_Ut>(__flags); } + }; - void - _M_notify(__platform_wait_t* __addr, [[maybe_unused]] bool __all, - bool __bare) noexcept - { -#ifdef _GLIBCXX_HAVE_PLATFORM_WAIT - if (__addr == &_M_ver) - { - __atomic_fetch_add(__addr, 1, __ATOMIC_SEQ_CST); - __all = true; - } - - if (__bare || _M_waiting()) - __platform_notify(__addr, __all); -#else + // Utility for populating a __wait_args_base structure. + struct __wait_args : __wait_args_base + { + template<typename _Tp> requires (!is_same_v<_Tp, __wait_args>) + explicit + __wait_args(const _Tp* __addr, bool __bare_wait = false) noexcept + : __wait_args_base{ _S_flags_for(__addr, __bare_wait) } { - lock_guard<mutex> __l(_M_mtx); - __atomic_fetch_add(__addr, 1, __ATOMIC_RELAXED); + _M_obj = __addr; // Might be replaced by _M_setup_wait + if constexpr (__waitable<_Tp>) + // __wait_impl might be able to wait directly on __addr + // instead of using a proxy, depending on its size. + _M_obj_size = sizeof(_Tp); } - if (__bare || _M_waiting()) - _M_cv.notify_all(); -#endif - } - static __waiter_pool_base& - _S_for(const void* __addr) noexcept + __wait_args(const __platform_wait_t* __addr, __platform_wait_t __old, + int __order, bool __bare_wait = false) noexcept + : __wait_args(__addr, __bare_wait) { - constexpr __UINTPTR_TYPE__ __ct = 16; - static __waiter_pool_base __w[__ct]; - auto __key = ((__UINTPTR_TYPE__)__addr >> 2) % __ct; - return __w[__key]; + _M_order = __order; + _M_old = __old; } - }; - struct __waiter_pool : __waiter_pool_base - { - void - _M_do_wait(const __platform_wait_t* __addr, __platform_wait_t __old) noexcept - { -#ifdef _GLIBCXX_HAVE_PLATFORM_WAIT - __platform_wait(__addr, __old); -#else - __platform_wait_t __val; - __atomic_load(__addr, &__val, __ATOMIC_SEQ_CST); - if (__val == __old) - { - lock_guard<mutex> __l(_M_mtx); - __atomic_load(__addr, &__val, __ATOMIC_RELAXED); - if (__val == __old) - _M_cv.wait(_M_mtx); - } -#endif // __GLIBCXX_HAVE_PLATFORM_WAIT - } - }; + __wait_args(const __wait_args&) noexcept = default; + __wait_args& operator=(const __wait_args&) noexcept = default; - template<typename _Tp> - struct __waiter_base - { - using __waiter_type = _Tp; - - __waiter_type& _M_w; - __platform_wait_t* _M_addr; - - template<typename _Up> - static __platform_wait_t* - _S_wait_addr(const _Up* __a, __platform_wait_t* __b) - { - if constexpr (__platform_wait_uses_type<_Up>) - return reinterpret_cast<__platform_wait_t*>(const_cast<_Up*>(__a)); - else - return __b; - } - - static __waiter_type& - _S_for(const void* __addr) noexcept + template<typename _Tp, typename _ValFn> + _Tp + _M_setup_wait(const _Tp* __addr, _ValFn __vfn, + __wait_result_type __res = {}) { - static_assert(sizeof(__waiter_type) == sizeof(__waiter_pool_base)); - auto& res = __waiter_pool_base::_S_for(__addr); - return reinterpret_cast<__waiter_type&>(res); - } - - template<typename _Up> - explicit __waiter_base(const _Up* __addr) noexcept - : _M_w(_S_for(__addr)) - , _M_addr(_S_wait_addr(__addr, &_M_w._M_ver)) - { } - - void - _M_notify(bool __all, bool __bare = false) noexcept - { _M_w._M_notify(_M_addr, __all, __bare); } - - template<typename _Up, typename _ValFn, - typename _Spin = __default_spin_policy> - static bool - _S_do_spin_v(__platform_wait_t* __addr, - const _Up& __old, _ValFn __vfn, - __platform_wait_t& __val, - _Spin __spin = _Spin{ }) - { - auto const __pred = [=] - { return !__detail::__atomic_compare(__old, __vfn()); }; - - if constexpr (__platform_wait_uses_type<_Up>) + static_assert(is_same_v<_Tp, decay_t<decltype(__vfn())>>); + + if (__res._M_has_val) // A previous wait loaded a recent value. + { + _M_old = __res._M_val; + if constexpr (!__platform_wait_uses_type<_Tp>) + { + // __res._M_val might be the value of a proxy wait object, + // not the value of *__addr. Call __vfn() to get new value. + return __vfn(); + } + // Not a proxy wait, so the value in __res._M_val was loaded + // from *__addr and we don't need to call __vfn(). + else if constexpr (sizeof(_Tp) == sizeof(__UINT32_TYPE__)) + return __builtin_bit_cast(_Tp, (__UINT32_TYPE__)_M_old); + else if constexpr (sizeof(_Tp) == sizeof(__UINT64_TYPE__)) + return __builtin_bit_cast(_Tp, (__UINT64_TYPE__)_M_old); + else + { + static_assert(false); // Unsupported size + return {}; + } + } + + if constexpr (!__platform_wait_uses_type<_Tp>) + if (_M_setup_proxy_wait(__addr)) { - __builtin_memcpy(&__val, &__old, sizeof(__val)); + // We will use a proxy wait for this object. + // The library has set _M_obj and _M_obj_size and _M_old. + // Call __vfn to load the current value from *__addr + // (which must happen after the call to _M_setup_proxy_wait). + return __vfn(); } - else - { - __atomic_load(__addr, &__val, __ATOMIC_ACQUIRE); - } - return __atomic_spin(__pred, __spin); - } - - template<typename _Up, typename _ValFn, - typename _Spin = __default_spin_policy> - bool - _M_do_spin_v(const _Up& __old, _ValFn __vfn, - __platform_wait_t& __val, - _Spin __spin = _Spin{ }) - { return _S_do_spin_v(_M_addr, __old, __vfn, __val, __spin); } - - template<typename _Pred, - typename _Spin = __default_spin_policy> - static bool - _S_do_spin(const __platform_wait_t* __addr, - _Pred __pred, - __platform_wait_t& __val, - _Spin __spin = _Spin{ }) - { - __atomic_load(__addr, &__val, __ATOMIC_ACQUIRE); - return __atomic_spin(__pred, __spin); - } - - template<typename _Pred, - typename _Spin = __default_spin_policy> - bool - _M_do_spin(_Pred __pred, __platform_wait_t& __val, - _Spin __spin = _Spin{ }) - { return _S_do_spin(_M_addr, __pred, __val, __spin); } - }; - - template<typename _EntersWait> - struct __waiter : __waiter_base<__waiter_pool> - { - using __base_type = __waiter_base<__waiter_pool>; - template<typename _Tp> - explicit __waiter(const _Tp* __addr) noexcept - : __base_type(__addr) - { - if constexpr (_EntersWait::value) - _M_w._M_enter_wait(); - } + // We will use a futex-like operation to wait on this object, + // and so can just load the value and store it into _M_old. + auto __val = __vfn(); + // We have to consider various sizes, because a future libstdc++.so + // might enable non-proxy waits for additional sizes. + if constexpr (sizeof(_Tp) == sizeof(__UINT64_TYPE__)) + _M_old = __builtin_bit_cast(__UINT64_TYPE__, __val); + else if constexpr (sizeof(_Tp) == sizeof(__UINT32_TYPE__)) + _M_old = __builtin_bit_cast(__UINT32_TYPE__, __val); + else if constexpr (sizeof(_Tp) == sizeof(__UINT16_TYPE__)) + _M_old = __builtin_bit_cast(__UINT16_TYPE__, __val); + else if constexpr (sizeof(_Tp) == sizeof(__UINT8_TYPE__)) + _M_old = __builtin_bit_cast(__UINT8_TYPE__, __val); + else // _M_setup_proxy_wait should have returned true for this type! + __glibcxx_assert(false); + return __val; + } - ~__waiter() + private: + // Returns true if a proxy wait will be used for __addr, false otherwise. + // If true, _M_wait_state, _M_obj, _M_obj_size, and _M_old are set. + // If false, data members are unchanged. + bool + _M_setup_proxy_wait(const void* __addr); + + template<typename _Tp> + static constexpr __wait_flags + _S_flags_for(const _Tp*, bool __bare_wait) noexcept { - if constexpr (_EntersWait::value) - _M_w._M_leave_wait(); + using enum __wait_flags; + __wait_flags __res = __abi_version | __do_spin; + if (!__bare_wait) + __res |= __track_contention; + return __res; } + }; - template<typename _Tp, typename _ValFn> - void - _M_do_wait_v(_Tp __old, _ValFn __vfn) - { - do - { - __platform_wait_t __val; - if (__base_type::_M_do_spin_v(__old, __vfn, __val)) - return; - __base_type::_M_w._M_do_wait(__base_type::_M_addr, __val); - } - while (__detail::__atomic_compare(__old, __vfn())); - } - - template<typename _Pred> - void - _M_do_wait(_Pred __pred) noexcept - { - do - { - __platform_wait_t __val; - if (__base_type::_M_do_spin(__pred, __val)) - return; - __base_type::_M_w._M_do_wait(__base_type::_M_addr, __val); - } - while (!__pred()); - } - }; + __wait_result_type + __wait_impl(const void* __addr, __wait_args_base&); - using __enters_wait = __waiter<std::true_type>; - using __bare_wait = __waiter<std::false_type>; + void + __notify_impl(const void* __addr, bool __all, const __wait_args_base&); } // namespace __detail - template<typename _Tp, typename _ValFn> + // Wait on __addr while __pred(__vfn()) is false. + // If __bare_wait is false, increment a counter while waiting. + // For callers that keep their own count of waiters, use __bare_wait=true. + // The effect of __vfn() must be an atomic load from __addr and nothing else. + template<typename _Tp, typename _Pred, typename _ValFn> void - __atomic_wait_address_v(const _Tp* __addr, _Tp __old, - _ValFn __vfn) noexcept + __atomic_wait_address(const _Tp* __addr, _Pred&& __pred, _ValFn&& __vfn, + bool __bare_wait = false) noexcept { - __detail::__enters_wait __w(__addr); - __w._M_do_wait_v(__old, __vfn); + __detail::__wait_args __args{ __addr, __bare_wait }; + _Tp __val = __args._M_setup_wait(__addr, __vfn); + while (!__pred(__val)) + { + auto __res = __detail::__wait_impl(__addr, __args); + __val = __args._M_setup_wait(__addr, __vfn, __res); + } + // C++26 will return __val } - template<typename _Tp, typename _Pred> - void - __atomic_wait_address(const _Tp* __addr, _Pred __pred) noexcept - { - __detail::__enters_wait __w(__addr); - __w._M_do_wait(__pred); - } + // Wait on __addr while *__addr == __old is true. + inline void + __atomic_wait_address_v(const __detail::__platform_wait_t* __addr, + __detail::__platform_wait_t __old, + int __order, bool __bare_wait = false) + { + // This function must not be used if __wait_impl might use a proxy wait: + __glibcxx_assert(__platform_wait_uses_type<__detail::__platform_wait_t>); - // This call is to be used by atomic types which track contention externally - template<typename _Pred> + __detail::__wait_args __args{ __addr, __old, __order, __bare_wait }; + // C++26 will not ignore the return value here + __detail::__wait_impl(__addr, __args); + } + + // Wait on __addr while __vfn() == __old is true. + template<typename _Tp, typename _ValFn> void - __atomic_wait_address_bare(const __detail::__platform_wait_t* __addr, - _Pred __pred) noexcept + __atomic_wait_address_v(const _Tp* __addr, _Tp __old, + _ValFn __vfn) noexcept { -#ifdef _GLIBCXX_HAVE_PLATFORM_WAIT - do - { - __detail::__platform_wait_t __val; - if (__detail::__bare_wait::_S_do_spin(__addr, __pred, __val)) - return; - __detail::__platform_wait(__addr, __val); - } - while (!__pred()); -#else // !_GLIBCXX_HAVE_PLATFORM_WAIT - __detail::__bare_wait __w(__addr); - __w._M_do_wait(__pred); -#endif + auto __pfn = [&](const _Tp& __val) + { return !__detail::__atomic_eq(__old, __val); }; + std::__atomic_wait_address(__addr, __pfn, forward<_ValFn>(__vfn)); } template<typename _Tp> void - __atomic_notify_address(const _Tp* __addr, bool __all) noexcept + __atomic_notify_address(const _Tp* __addr, bool __all, + bool __bare_wait = false) noexcept { - __detail::__bare_wait __w(__addr); - __w._M_notify(__all); + __detail::__wait_args __args{ __addr, __bare_wait }; + __detail::__notify_impl(__addr, __all, __args); } - // This call is to be used by atomic types which track contention externally - inline void - __atomic_notify_address_bare(const __detail::__platform_wait_t* __addr, - bool __all) noexcept - { -#ifdef _GLIBCXX_HAVE_PLATFORM_WAIT - __detail::__platform_notify(__addr, __all); -#else - __detail::__bare_wait __w(__addr); - __w._M_notify(__all, true); -#endif - } _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // __glibcxx_atomic_wait diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index a087e63..b1db722 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -269,8 +269,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 void _M_set_length(size_type __n) { - _M_length(__n); traits_type::assign(_M_data()[__n], _CharT()); + _M_length(__n); } _GLIBCXX20_CONSTEXPR @@ -411,7 +411,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 if (__pos > this->size()) __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > " "this->size() (which is %zu)"), - __s, __pos, this->size()); + __s, (size_t)__pos, (size_t)this->size()); return __pos; } @@ -1164,7 +1164,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { size_type __sz = _M_string_length; if (__sz > max_size ()) - __builtin_unreachable (); + __builtin_unreachable(); return __sz; } @@ -1279,7 +1279,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 size_t __sz = _M_is_local() ? size_type(_S_local_capacity) : _M_allocated_capacity; if (__sz < _S_local_capacity || __sz > max_size ()) - __builtin_unreachable (); + __builtin_unreachable(); return __sz; } @@ -3442,6 +3442,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { return basic_string(*this, _M_check(__pos, "basic_string::substr"), __n); } +#ifdef __glibcxx_string_subview // >= C++26 + /** + * @brief Get a subview. + * @param __pos Index of first character (default 0). + * @param __n Number of characters in subview (default remainder). + * @return The subview. + * @throw std::out_of_range If __pos > size(). + * + * Construct and return a subview using the `__n` characters starting at + * `__pos`. If the string is too short, use the remainder of the + * characters. If `__pos` is beyond the end of the string, out_of_range + * is thrown. + */ + [[nodiscard]] + constexpr basic_string_view<_CharT, _Traits> + subview(size_type __pos = 0, size_type __n = npos) const + { return __sv_type(*this).subview(__pos, __n); } +#endif + /** * @brief Compare to a string. * @param __str String to compare against. diff --git a/libstdc++-v3/include/bits/binders.h b/libstdc++-v3/include/bits/binders.h new file mode 100644 index 0000000..9724717 --- /dev/null +++ b/libstdc++-v3/include/bits/binders.h @@ -0,0 +1,237 @@ +// Implementation of std::move_only_function, std::copyable_function +// and std::function_ref -*- C++ -*- + +// Copyright The GNU Toolchain Authors. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file include/bits/binder.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _GLIBCXX_BINDERS_H +#define _GLIBCXX_BINDERS_H 1 + +#ifdef _GLIBCXX_SYSHDR +#pragma GCC system_header +#endif + +#if __cplusplus >= 202002L + +#include <bits/invoke.h> +#include <bits/move.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template<size_t, typename _Tp> + struct _Indexed_bound_arg + { + [[no_unique_address]] _Tp _M_val; + }; + + template<typename... _IndexedArgs> + struct _Bound_arg_storage : _IndexedArgs... + { + template<bool _Back, typename _Fd, typename _Self, typename... _CallArgs> + static constexpr + decltype(auto) + _S_apply(_Fd&& __fd, _Self&& __self, _CallArgs&&... __call_args) + { + if constexpr (_Back) + return std::__invoke(std::forward<_Fd>(__fd), + std::forward<_CallArgs>(__call_args)..., + __like_t<_Self, _IndexedArgs>(__self)._M_val...); + else + return std::__invoke(std::forward<_Fd>(__fd), + __like_t<_Self, _IndexedArgs>(__self)._M_val..., + std::forward<_CallArgs>(__call_args)...); + } + }; + + template<typename... _BoundArgs, typename... _Args> + constexpr auto + __make_bound_args(_Args&&... __args) + { + if constexpr (sizeof...(_BoundArgs) == 1) + // pack has one element, so return copy of arg + return (_BoundArgs(std::forward<_Args>(__args)), ...); + else + { + auto __impl = [&]<size_t... _Inds>(index_sequence<_Inds...>) + { + return _Bound_arg_storage<_Indexed_bound_arg<_Inds, _BoundArgs>...> + { {_BoundArgs(std::forward<_Args>(__args))}... }; + }; + return __impl(index_sequence_for<_BoundArgs...>()); + } + } + + template<bool _Back, typename _Fd, typename... _BoundArgs> + class _Binder + { + template<typename _Self, typename... _CallArgs> + using _Result_t = __conditional_t< + _Back, + invoke_result<__like_t<_Self, _Fd>, + _CallArgs..., __like_t<_Self, _BoundArgs>...>, + invoke_result<__like_t<_Self, _Fd>, + __like_t<_Self, _BoundArgs>..., _CallArgs...>>::type; + + template<typename _Self, typename... _CallArgs> + static consteval bool + _S_noexcept_invocable() + { + if constexpr (_Back) + return is_nothrow_invocable_v< __like_t<_Self, _Fd>, + _CallArgs..., __like_t<_Self, _BoundArgs>...>; + else + return is_nothrow_invocable_v<__like_t<_Self, _Fd>, + __like_t<_Self, _BoundArgs>..., _CallArgs...>; + } + + public: + static_assert(is_move_constructible_v<_Fd>); + static_assert((is_move_constructible_v<_BoundArgs> && ...)); + + // First parameter is to ensure this constructor is never used + // instead of the copy/move constructor. + template<typename _Fn, typename... _Args> + explicit constexpr + _Binder(int, _Fn&& __fn, _Args&&... __args) + noexcept(__and_<is_nothrow_constructible<_Fd, _Fn>, + is_nothrow_constructible<_BoundArgs, _Args>...>::value) + : _M_fd(std::forward<_Fn>(__fn)), + _M_bound_args(__make_bound_args<_BoundArgs...>(std::forward<_Args>(__args)...)) + { static_assert(sizeof...(_Args) == sizeof...(_BoundArgs)); } + +#if _GLIBCXX_EXPLICIT_THIS_PARAMETER +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wc++23-extensions" // deducing this + template<typename _Self, typename... _CallArgs> + constexpr _Result_t<_Self, _CallArgs...> + operator()(this _Self&& __self, _CallArgs&&... __call_args) + noexcept(_S_noexcept_invocable<_Self, _CallArgs...>()) + { + return _S_call(__like_t<_Self, _Binder>(__self), + std::forward<_CallArgs>(__call_args)...); + } +# pragma GCC diagnostic pop +#else + template<typename... _CallArgs> + requires true + constexpr _Result_t<_Binder&, _CallArgs...> + operator()(_CallArgs&&... __call_args) & + noexcept(_S_noexcept_invocable<_Binder&, _CallArgs...>()) + { + return _S_call(*this, std::forward<_CallArgs>(__call_args)...); + } + + template<typename... _CallArgs> + requires true + constexpr _Result_t<const _Binder&, _CallArgs...> + operator()(_CallArgs&&... __call_args) const & + noexcept(_S_noexcept_invocable<const _Binder&, _CallArgs...>()) + { + return _S_call(*this, std::forward<_CallArgs>(__call_args)...); + } + + template<typename... _CallArgs> + requires true + constexpr _Result_t<_Binder&&, _CallArgs...> + operator()(_CallArgs&&... __call_args) && + noexcept(_S_noexcept_invocable<_Binder&&, _CallArgs...>()) + { + return _S_call(std::move(*this), + std::forward<_CallArgs>(__call_args)...); + } + + template<typename... _CallArgs> + requires true + constexpr _Result_t<const _Binder&&, _CallArgs...> + operator()(_CallArgs&&... __call_args) const && + noexcept(_S_noexcept_invocable<const _Binder&&, _CallArgs...>()) + { + return _S_call(std::move(*this), + std::forward<_CallArgs>(__call_args)...); + } + + template<typename... _CallArgs> + void operator()(_CallArgs&&...) & = delete; + + template<typename... _CallArgs> + void operator()(_CallArgs&&...) const & = delete; + + template<typename... _CallArgs> + void operator()(_CallArgs&&...) && = delete; + + template<typename... _CallArgs> + void operator()(_CallArgs&&...) const && = delete; +#endif + + template<typename _Tp, typename... _CallArgs> + static constexpr + decltype(auto) + _S_call(_Tp&& __g, _CallArgs&&... __call_args) + { + if constexpr (sizeof...(_BoundArgs) > 1) + return _BoundArgsStorage::template _S_apply<_Back>( + std::forward<_Tp>(__g)._M_fd, + std::forward<_Tp>(__g)._M_bound_args, + std::forward<_CallArgs>(__call_args)...); + else if constexpr (sizeof...(_BoundArgs) == 0) + return std::__invoke(std::forward<_Tp>(__g)._M_fd, + std::forward<_CallArgs>(__call_args)...); + else if constexpr (_Back) // sizeof...(_BoundArgs) == 1 + return std::__invoke(std::forward<_Tp>(__g)._M_fd, + std::forward<_CallArgs>(__call_args)..., + std::forward<_Tp>(__g)._M_bound_args); + else // !_Back && sizeof...(_BoundArgs) == 1 + return std::__invoke(std::forward<_Tp>(__g)._M_fd, + std::forward<_Tp>(__g)._M_bound_args, + std::forward<_CallArgs>(__call_args)...); + } + + private: + using _BoundArgsStorage + // _BoundArgs are required to be move-constructible, so this is valid. + = decltype(__make_bound_args<_BoundArgs...>(std::declval<_BoundArgs>()...)); + + [[no_unique_address]] _Fd _M_fd; + [[no_unique_address]] _BoundArgsStorage _M_bound_args; + }; + + template<typename _Fn, typename... _Args> + using _Bind_front_t = _Binder<false, decay_t<_Fn>, decay_t<_Args>...>; + + // for zero bounds args behavior of bind_front and bind_back is the same, + // so reuse _Bind_front_t, i.e. _Binder<false, ...> + template<typename _Fn, typename... _Args> + using _Bind_back_t + = _Binder<(sizeof...(_Args) > 0), decay_t<_Fn>, decay_t<_Args>...>; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // __cplusplus >= 202002L +#endif // _GLIBCXX_BINDERS_H diff --git a/libstdc++-v3/include/bits/boost_concept_check.h b/libstdc++-v3/include/bits/boost_concept_check.h index 7a99f74..a1f488d 100644 --- a/libstdc++-v3/include/bits/boost_concept_check.h +++ b/libstdc++-v3/include/bits/boost_concept_check.h @@ -68,6 +68,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-local-typedefs" +#pragma GCC diagnostic ignored "-Wlong-long" #define _IsUnused __attribute__ ((__unused__)) diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index 676f5ee..e6d8f18 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -273,6 +273,12 @@ #define _GLIBCXX_NOEXCEPT_QUAL #endif +#if __cpp_auto_cast +# define _GLIBCXX_AUTO_CAST(X) auto(X) +#else +# define _GLIBCXX_AUTO_CAST(X) ::std::__decay_t<decltype((X))>(X) +#endif + // Macro for extern template, ie controlling template linkage via use // of extern keyword on template declaration. As documented in the g++ // manual, it inhibits all implicit instantiations and is used @@ -921,6 +927,13 @@ namespace __gnu_cxx # define _GLIBCXX_USE_BUILTIN_TRAIT(BT) 0 #endif +// Whether deducing this is usable either officially, if in C++23 mode, or +// as an extension (Clang doesn't support the latter). +#if __cpp_explicit_this_parameter \ + || (__cplusplus >= 201103L && __GNUC__ >= 14 && !defined(_GLIBCXX_CLANG)) +# define _GLIBCXX_EXPLICIT_THIS_PARAMETER 202110L +#endif + // Mark code that should be ignored by the compiler, but seen by Doxygen. #define _GLIBCXX_DOXYGEN_ONLY(X) diff --git a/libstdc++-v3/include/bits/chrono.h b/libstdc++-v3/include/bits/chrono.h index fad2162..4dc3998 100644 --- a/libstdc++-v3/include/bits/chrono.h +++ b/libstdc++-v3/include/bits/chrono.h @@ -1244,6 +1244,7 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2) now() noexcept; // Map to C API + [[__gnu__::__always_inline__]] static std::time_t to_time_t(const time_point& __t) noexcept { @@ -1251,6 +1252,7 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2) (__t.time_since_epoch()).count()); } + [[__gnu__::__always_inline__]] static time_point from_time_t(std::time_t __t) noexcept { @@ -1513,6 +1515,80 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) } // namespace filesystem #endif // C++17 && HOSTED +#if _GLIBCXX_HOSTED +#if ! defined _GLIBCXX_NO_SLEEP || defined _GLIBCXX_HAS_GTHREADS \ + || _GLIBCXX_HAVE_LINUX_FUTEX +namespace chrono +{ +/// @cond undocumented + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++17-extensions" + // Convert a chrono::duration to a relative time represented as timespec + // (e.g. for use with nanosleep). + template<typename _Rep, typename _Period> + [[__nodiscard__]] _GLIBCXX14_CONSTEXPR inline + struct ::timespec + __to_timeout_timespec(const duration<_Rep, _Period>& __d) + { + struct ::timespec __ts{}; + + if (__d < __d.zero()) // Negative timeouts don't make sense. + return __ts; + + if constexpr (ratio_greater<_Period, ratio<1>>::value + || treat_as_floating_point<_Rep>::value) + { + // Converting from e.g. chrono::hours::max() to chrono::seconds + // would evaluate LLONG_MAX * 3600 which would overflow. + // Limit to chrono::seconds::max(). + chrono::duration<double> __fmax(chrono::seconds::max()); + if (__d > __fmax) [[__unlikely__]] + return chrono::__to_timeout_timespec(chrono::seconds::max()); + } + + auto __s = chrono::duration_cast<chrono::seconds>(__d); + + if constexpr (is_integral<time_t>::value) // POSIX.1-2001 allows floating + { + // Also limit to time_t maximum (only relevant for 32-bit time_t). + constexpr auto __tmax = numeric_limits<time_t>::max(); + if (__s.count() > __tmax) [[__unlikely__]] + { + __ts.tv_sec = __tmax; + return __ts; + } + } + + auto __ns = chrono::duration_cast<chrono::nanoseconds>(__d - __s); + + if constexpr (treat_as_floating_point<_Rep>::value) + if (__ns.count() > 999999999) [[__unlikely__]] + __ns = chrono::nanoseconds(999999999); + + __ts.tv_sec = static_cast<time_t>(__s.count()); + __ts.tv_nsec = static_cast<long>(__ns.count()); + return __ts; + } +#pragma GCC diagnostic pop + + // Convert a chrono::time_point to an absolute time represented as timespec. + // All times before the epoch get converted to the epoch, so this assumes + // that we only use it for clocks where that's true. + // It should be safe to use this for system_clock and steady_clock. + template<typename _Clock, typename _Dur> + [[__nodiscard__]] _GLIBCXX14_CONSTEXPR inline + struct ::timespec + __to_timeout_timespec(const time_point<_Clock, _Dur>& __t) + { + return chrono::__to_timeout_timespec(__t.time_since_epoch()); + } + +/// @endcond +} // namespace chrono +#endif // !NO_SLEEP || HAS_GTHREADS || HAVE_LINUX_FUTEX +#endif // HOSTED + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/chrono_io.h b/libstdc++-v3/include/bits/chrono_io.h index ace8b9f..3b1f586 100644 --- a/libstdc++-v3/include/bits/chrono_io.h +++ b/libstdc++-v3/include/bits/chrono_io.h @@ -37,7 +37,6 @@ #if __cplusplus >= 202002L #include <sstream> // ostringstream -#include <iomanip> // setw, setfill #include <format> #include <charconv> // from_chars #include <stdexcept> // __sso_string @@ -189,11 +188,6 @@ namespace __format { [[noreturn,__gnu__::__always_inline__]] inline void - __no_timezone_available() - { __throw_format_error("format error: no timezone available for %Z or %z"); } - - [[noreturn,__gnu__::__always_inline__]] - inline void __not_valid_for_duration() { __throw_format_error("format error: chrono-format-spec not valid for " "chrono::duration"); } @@ -204,45 +198,355 @@ namespace __format { __throw_format_error("format error: chrono-format-spec not valid for " "argument type"); } + // Represents the information provided by a chrono type. + // e.g. month_weekday has month and weekday but no year or time of day, + // hh_mm_ss has time of day but no date, sys_time is time_point+timezone. + enum class _ChronoParts : unsigned short { + _None = 0, _TotalSeconds = 1u, _Subseconds = 1u << 2, + + // time since epoch + _EpochUnits = 1u << 3, _UnitSuffix = 1u << 4, + _EpochSeconds = _EpochUnits | _TotalSeconds, + + // local (wall) time + _LocalDays = 1u << 5, + _LocalSeconds = _LocalDays | _TotalSeconds, + + _Year = 1u << 6, _Month = 1u << 7, _Day = 1u << 8, + _Weekday = 1u << 9, _WeekdayIndex = 1u << 10, _DayOfYear = 1u << 11, + _IndexedWeekday = _Weekday | _WeekdayIndex, + _YearMonthDay = _Year | _Month | _Day, + _Date = _LocalDays | _YearMonthDay | _IndexedWeekday | _DayOfYear, + + _HoursMinutesSeconds = 1u << 12, + _TimeOfDay = _HoursMinutesSeconds | _Subseconds, + _Time = _TimeOfDay | _TotalSeconds, + _EpochTime = _Time | _EpochUnits | _UnitSuffix, + _DateTime = _Date | _Time, + + _ZoneAbbrev = 1u << 13, _ZoneOffset = 1u << 14, + _TimeZone = _ZoneAbbrev | _ZoneOffset, + _ZonedDateTime = _DateTime | _TimeZone, + }; + + [[__gnu__::__always_inline__]] + constexpr _ChronoParts + operator&(_ChronoParts __x, _ChronoParts __y) noexcept + { return static_cast<_ChronoParts>((unsigned)__x & (unsigned)__y); } + + [[__gnu__::__always_inline__]] + constexpr _ChronoParts& + operator&=(_ChronoParts& __x, _ChronoParts __y) noexcept + { return __x = __x & __y; } + + [[__gnu__::__always_inline__]] + constexpr _ChronoParts + operator|(_ChronoParts __x, _ChronoParts __y) noexcept + { return static_cast<_ChronoParts>((unsigned short)__x | (unsigned short)__y); } + + [[__gnu__::__always_inline__]] + constexpr _ChronoParts& + operator|=(_ChronoParts& __x, _ChronoParts __y) noexcept + { return __x = __x | __y; } + + // returns copy of x with all bits from y unset. + [[__gnu__::__always_inline__]] + constexpr _ChronoParts + operator-(_ChronoParts __x, _ChronoParts __y) noexcept + { return static_cast<_ChronoParts>((unsigned short)__x & ~(unsigned short)__y); } + + // unsets all bits of x that are set in y + [[__gnu__::__always_inline__]] + constexpr _ChronoParts& + operator-=(_ChronoParts& __x, _ChronoParts __y) noexcept + { return __x = __x - __y; } + + [[__gnu__::__always_inline__]] + constexpr bool + operator==(_ChronoParts __x, decltype(nullptr)) noexcept + { return (unsigned short)__x == 0; } + template<typename _CharT> struct _ChronoSpec : _Spec<_CharT> { - basic_string_view<_CharT> _M_chrono_specs; + // When _M_prec_kind is _WP_none, the _M_prec contains the default + // value of fraction digits to be used for time '%S'. - // Use one of the reserved bits in __format::_Spec<C>. + // Placed in tail-padding of __format::_Spec<C>. // This indicates that a locale-dependent conversion specifier such as // %a is used in the chrono-specs. This is not the same as the // _Spec<C>::_M_localized member which indicates that "L" was present // in the format-spec, e.g. "{:L%a}" is localized and locale-specific, // but "{:L}" is only localized and "{:%a}" is only locale-specific. - constexpr bool - _M_locale_specific() const noexcept - { return this->_M_reserved; } + unsigned _M_locale_specific : 1; + // Indicates if parts that are checked for ok come directly from the + // input, instead of being computed. + unsigned _M_needs_ok_check : 1; + // Indicates that duration should be treated as floating point. + unsigned _M_floating_point_rep : 1; + // Indicate that duration uses user-defined representation. + unsigned _M_custom_rep : 1; + unsigned _M_unused : 4; + + // Chrono parts required by format specs + _ChronoParts _M_needed; + basic_string_view<_CharT> _M_chrono_specs; - constexpr void - _M_locale_specific(bool __b) noexcept - { this->_M_reserved = __b; } + [[__gnu__::__always_inline__]] + constexpr bool + _M_needs(_ChronoParts __parts) const + { return (_M_needed & __parts) != 0; } }; - // Represents the information provided by a chrono type. - // e.g. month_weekday has month and weekday but no year or time of day, - // hh_mm_ss has time of day but no date, sys_time is time_point+timezone. - enum _ChronoParts { - _Year = 1, _Month = 2, _Day = 4, _Weekday = 8, _TimeOfDay = 16, - _TimeZone = 32, - _Date = _Year | _Month | _Day | _Weekday, - _DateTime = _Date | _TimeOfDay, - _ZonedDateTime = _DateTime | _TimeZone, - _Duration = 128 // special case + template<typename _CharT> + struct _ChronoFormats + { + using _String_view = basic_string_view<_CharT>; + + static consteval + _String_view + _S_ftz() noexcept + { return _GLIBCXX_WIDEN("%F %T %Z"); } + + static consteval + _String_view + _S_ft() noexcept + { return _S_ftz().substr(0, 5); } + + static consteval + _String_view + _S_f() noexcept + { return _S_ftz().substr(0, 2); } + + static consteval + _String_view + _S_t() noexcept + { return _S_ftz().substr(3, 2); } + + static consteval + _String_view + _S_ymd() noexcept + { return _GLIBCXX_WIDEN("%Y/%b/%d"); } + + static consteval + _String_view + _S_ym() noexcept + { return _S_ymd().substr(0, 5); } + + static consteval + _String_view + _S_md() noexcept + { return _S_ymd().substr(3); } + + static consteval + _String_view + _S_y() noexcept + { return _S_ymd().substr(0, 2); } + + static consteval + _String_view + _S_m() noexcept + { return _S_ymd().substr(3, 2); } + + static consteval + _String_view + _S_d() noexcept + { return _S_ymd().substr(6, 2); } + + static consteval + _String_view + _S_ymwi() noexcept + // %\0 is extension for handling weekday index + { return _String_view(_GLIBCXX_WIDEN("%Y/%b/%a[%\0]"), 12); } + + static consteval + _String_view + _S_mwi() noexcept + { return _S_ymwi().substr(3); } + + static consteval + _String_view + _S_wi() noexcept + { return _S_ymwi().substr(6); } + + static consteval + _String_view + _S_w() noexcept + { return _S_ymwi().substr(6, 2); } + + static consteval + _String_view + _S_ymwl() noexcept + { return _GLIBCXX_WIDEN("%Y/%b/%a[last]"); } + + static consteval + _String_view + _S_mwl() noexcept + { return _S_ymwl().substr(3); } + + static consteval + _String_view + _S_wl() noexcept + { return _S_ymwl().substr(6); } + + static consteval + _String_view + _S_yml() noexcept + { return _GLIBCXX_WIDEN("%Y/%b/last"); } + + static consteval + _String_view + _S_ml() noexcept + { return _S_yml().substr(3); } }; - constexpr _ChronoParts - operator|(_ChronoParts __x, _ChronoParts __y) noexcept - { return static_cast<_ChronoParts>((int)__x | (int)__y); } + template<typename _CharT> + struct _ChronoData + { + static constexpr unsigned _S_max_prec = 18; + using _Attoseconds = chrono::duration<__UINT_LEAST64_TYPE__, atto>; + + using _FormatContext + = basic_format_context<_Sink_iter<_CharT>, _CharT>; + using _FormatArgs = basic_format_args<_FormatContext>; + static inline auto _S_args = std::make_format_args<_FormatContext>(); + + _ChronoData() = default; + _ChronoData(_ChronoData&&) = delete; + + // time since epoch + chrono::seconds _M_eseconds; + // n.b. due offset being seconds or coarser, local and epoch subseconds + // has the same value + _Attoseconds _M_subseconds; + // _M_ereps.get(0) stores duration units + // _M_ereps.get(1) stores subseconds units + // _M_ereps.get(2) stores precision + _FormatArgs _M_ereps = _S_args; + basic_string_view<_CharT> _M_unit_suffix; + + // local (wall) time + chrono::local_seconds _M_lseconds; + chrono::local_days _M_ldays; + + chrono::year _M_year; + chrono::month _M_month; + chrono::day _M_day; + chrono::weekday _M_weekday; + unsigned char _M_weekday_index; + chrono::days _M_day_of_year; + + bool _M_is_neg; + chrono::hours _M_hours; + chrono::minutes _M_minutes; + chrono::seconds _M_seconds; + + chrono::seconds _M_zone_offset; + basic_string_view<_CharT> _M_zone_abbrev; + const char* _M_zone_cstr = ""; + + template<typename _YearMonth> + [[__gnu__::__always_inline__]] + _ChronoParts + _M_fill_year_month(const _YearMonth& __ym, _ChronoParts __parts) + { + _M_year = __ym.year(); + __parts -= _ChronoParts::_Year; + _M_month = __ym.month(); + __parts -= _ChronoParts::_Month; + return __parts; + } - constexpr _ChronoParts& - operator|=(_ChronoParts& __x, _ChronoParts __y) noexcept - { return __x = __x | __y; } + [[__gnu__::__always_inline__]] + _ChronoParts + _M_fill_day(chrono::day __d, _ChronoParts __parts) + { + _M_day = __d; + __parts -= _ChronoParts::_Day; + _M_weekday_index = ((unsigned)__d + 6u) / 7u; + __parts -= _ChronoParts::_WeekdayIndex; + return __parts; + } + + [[__gnu__::__always_inline__]] + _ChronoParts + _M_fill_weekday(chrono::weekday_indexed __wi, _ChronoParts __parts) + { + _M_weekday = __wi.weekday(); + __parts -= _ChronoParts::_Weekday; + _M_weekday_index = __wi.index(); + __parts -= _ChronoParts::_WeekdayIndex; + return __parts; + } + + // pre: _M_year is set + [[__gnu__::__always_inline__]] + _ChronoParts + _M_fill_aux(chrono::local_days __ld, _ChronoParts __parts) + { + using namespace chrono; + if ((__parts & _ChronoParts::_Weekday) != 0) + _M_weekday = weekday(__ld); + __parts -= _ChronoParts::_Weekday; + if ((__parts & _ChronoParts::_DayOfYear) != 0) + // See "Calculating Ordinal Dates" at + // https://github.com/HowardHinnant/date/wiki/Examples-and-Recipes + _M_day_of_year = __ld - local_days(_M_year/January/0); + __parts -= _ChronoParts::_DayOfYear; + return __parts; + } + + // pre: _M_year is set + [[__gnu__::__always_inline__]] + _ChronoParts + _M_fill_ldays(chrono::local_days __ld, _ChronoParts __parts) + { + _M_ldays = __ld; + __parts -= _ChronoParts::_LocalDays; + return _M_fill_aux(__ld, __parts); + } + + void + _M_fill_time(chrono::seconds __d) + { + chrono::hh_mm_ss<chrono::seconds> __hms(__d); + _M_hours = __hms.hours(); + _M_minutes = __hms.minutes(); + _M_seconds = __hms.seconds(); + } + + void + _M_fill_date_time(chrono::local_seconds __ls, _ChronoParts __parts) + { + _M_ldays = chrono::floor<chrono::days>(__ls); + __parts -= _ChronoParts::_LocalDays; + if ((__parts & _ChronoParts::_HoursMinutesSeconds) != 0) + _M_fill_time(_M_lseconds - _M_ldays); + + if ((__parts & _ChronoParts::_Date) != 0) + { + const chrono::year_month_day __ymd(_M_ldays); + _M_fill_year_month(__ymd, __parts); + _M_fill_day(__ymd.day(), __parts); + _M_fill_aux(_M_ldays, __parts); + } + } + + void + _M_fill_zone(const char* __abbrev, const wchar_t* __wabbrev) + { + if constexpr (is_same_v<_CharT, char>) + _M_zone_abbrev = __abbrev; + else + _M_zone_abbrev = __wabbrev; + _M_zone_cstr = __abbrev; + } + + [[__gnu__::__always_inline__]] + void + _M_fill_utc_zone() + { _M_fill_zone("UTC", L"UTC"); } + }; // TODO rename this to chrono::__formatter? or chrono::__detail::__formatter? template<typename _CharT> @@ -251,268 +555,300 @@ namespace __format using __string_view = basic_string_view<_CharT>; using __string = basic_string<_CharT>; - template<typename _ParseContext> - constexpr typename _ParseContext::iterator - _M_parse(_ParseContext& __pc, _ChronoParts __parts) - { - auto __first = __pc.begin(); - auto __last = __pc.end(); - - _ChronoSpec<_CharT> __spec{}; - - auto __finalize = [this, &__spec] { - _M_spec = __spec; - }; - - auto __finished = [&] { - if (__first == __last || *__first == '}') - { - __finalize(); - return true; - } - return false; - }; + __formatter_chrono() = default; - if (__finished()) - return __first; - - __first = __spec._M_parse_fill_and_align(__first, __last); - if (__finished()) - return __first; + constexpr explicit + __formatter_chrono(_ChronoSpec<_CharT> __spec) noexcept + : _M_spec(__spec) + { } - __first = __spec._M_parse_width(__first, __last, __pc); - if (__finished()) - return __first; + constexpr typename basic_format_parse_context<_CharT>::iterator + _M_parse(basic_format_parse_context<_CharT>& __pc, _ChronoParts __parts, + const _ChronoSpec<_CharT>& __def) + { + auto __first = __pc.begin(); + auto __last = __pc.end(); + + _ChronoSpec<_CharT> __spec = __def; + + auto __finalize = [this, &__spec, &__def] { + using enum _ChronoParts; + _ChronoParts __checked + = __spec._M_debug ? _YearMonthDay|_IndexedWeekday + : _Month|_Weekday; + // n.b. for calendar types __def._M_needed contains only parts + // copied from the input, remaining ones are computed, and thus ok + __spec._M_needs_ok_check + = __spec._M_needs(__def._M_needed & __checked); + _M_spec = __spec; + }; - if (__parts & _ChronoParts::_Duration) + auto __finished = [&] { + if (__first == __last || *__first == '}') { - __first = __spec._M_parse_precision(__first, __last, __pc); - if (__finished()) - return __first; + __finalize(); + return true; } + return false; + }; - __first = __spec._M_parse_locale(__first, __last); - if (__finished()) - return __first; + if (__finished()) + return __first; - // Everything up to the end of the string or the first '}' is a - // chrono-specs string. Check it is valid. - { - __string_view __str(__first, __last - __first); - auto __end = __str.find('}'); - if (__end != __str.npos) - { - __str.remove_suffix(__str.length() - __end); - __last = __first + __end; - } - if (__str.find('{') != __str.npos) - __throw_format_error("chrono format error: '{' in chrono-specs"); - } + __first = __spec._M_parse_fill_and_align(__first, __last); + if (__finished()) + return __first; - // Parse chrono-specs in [first,last), checking each conversion-spec - // against __parts (so fail for %Y if no year in parts). - // Save range in __spec._M_chrono_specs. + __first = __spec._M_parse_width(__first, __last, __pc); + if (__finished()) + return __first; - const auto __chrono_specs = __first++; // Skip leading '%' - if (*__chrono_specs != '%') - __throw_format_error("chrono format error: no '%' at start of " - "chrono-specs"); + if (*__first == '.') + { + if ((__parts & _ChronoParts::_EpochUnits) == 0 + || !__spec._M_floating_point_rep) + __throw_format_error("format error: invalid precision for duration"); + + // Precision is allowed, but value is ignored. + __first = _Spec<_CharT>()._M_parse_precision(__first, __last, __pc); + // Still inditate that there was user supplied precision. + __spec._M_prec_kind = _WP_value; + if (__finished()) + return __first; + } - _CharT __mod{}; - bool __conv = true; - int __needed = 0; - bool __locale_specific = false; + __spec._M_localized = false; + __first = __spec._M_parse_locale(__first, __last); + if (__finished()) + return __first; - while (__first != __last) + // Everything up to the end of the string or the first '}' is a + // chrono-specs string. Check it is valid. + { + __string_view __str(__first, __last - __first); + auto __end = __str.find('}'); + if (__end != __str.npos) { - enum _Mods { _Mod_none, _Mod_E, _Mod_O, _Mod_E_O }; - _Mods __allowed_mods = _Mod_none; - - _CharT __c = *__first++; - switch (__c) - { - case 'a': - case 'A': - __needed = _Weekday; - __locale_specific = true; - break; - case 'b': - case 'h': - case 'B': - __needed = _Month; - __locale_specific = true; - break; - case 'c': - __needed = _DateTime; - __allowed_mods = _Mod_E; - __locale_specific = true; - break; - case 'C': - __needed = _Year; - __allowed_mods = _Mod_E; - break; - case 'd': - case 'e': - __needed = _Day; - __allowed_mods = _Mod_O; - break; - case 'D': - case 'F': - __needed = _Date; - break; - case 'g': - case 'G': - __needed = _Date; - break; - case 'H': - case 'I': - __needed = _TimeOfDay; - __allowed_mods = _Mod_O; - break; - case 'j': - if (!(__parts & _Duration)) - __needed = _Date; - break; - case 'm': - __needed = _Month; - __allowed_mods = _Mod_O; - break; - case 'M': - __needed = _TimeOfDay; - __allowed_mods = _Mod_O; - break; - case 'p': - case 'r': - __locale_specific = true; - [[fallthrough]]; - case 'R': - case 'T': - __needed = _TimeOfDay; - break; - case 'q': - case 'Q': - __needed = _Duration; - break; - case 'S': - __needed = _TimeOfDay; - __allowed_mods = _Mod_O; - break; - case 'u': - case 'w': - __needed = _Weekday; - __allowed_mods = _Mod_O; - break; - case 'U': - case 'V': - case 'W': - __needed = _Date; - __allowed_mods = _Mod_O; - break; - case 'x': - __needed = _Date; - __locale_specific = true; - __allowed_mods = _Mod_E; - break; - case 'X': - __needed = _TimeOfDay; - __locale_specific = true; - __allowed_mods = _Mod_E; - break; - case 'y': - __needed = _Year; - __allowed_mods = _Mod_E_O; - break; - case 'Y': - __needed = _Year; - __allowed_mods = _Mod_E; - break; - case 'z': - __needed = _TimeZone; - __allowed_mods = _Mod_E_O; - break; - case 'Z': - __needed = _TimeZone; - break; - case 'n': - case 't': - case '%': - break; - case 'O': - case 'E': - if (__mod) [[unlikely]] - { - __allowed_mods = _Mod_none; - break; - } - __mod = __c; - continue; - default: - __throw_format_error("chrono format error: invalid " - " specifier in chrono-specs"); - } + __str.remove_suffix(__str.length() - __end); + __last = __first + __end; + } + if (__str.find('{') != __str.npos) + __throw_format_error("chrono format error: '{' in chrono-specs"); + } - if ((__mod == 'E' && !(__allowed_mods & _Mod_E)) - || (__mod == 'O' && !(__allowed_mods & _Mod_O))) - __throw_format_error("chrono format error: invalid " - " modifier in chrono-specs"); - if (__mod && __c != 'z') - __locale_specific = true; - __mod = _CharT(); + // Parse chrono-specs in [first,last), checking each conversion-spec + // against __parts (so fail for %Y if no year in parts). + // Save range in __spec._M_chrono_specs. + __spec._M_debug = false; + __spec._M_locale_specific = false; + __spec._M_needed = _ChronoParts::_None; + __spec._M_chrono_specs = __string_view(); + + const auto __chrono_specs = __first++; // Skip leading '%' + if (*__chrono_specs != '%') + __throw_format_error("chrono format error: no '%' at start of " + "chrono-specs"); + + _CharT __mod{}; + bool __conv = true; + while (__first != __last) + { + enum _Mods { _Mod_none, _Mod_E, _Mod_O, _Mod_E_O }; + _Mods __allowed_mods = _Mod_none; - if ((__parts & __needed) != __needed) - __throw_format_error("chrono format error: format argument " - "does not contain the information " - "required by the chrono-specs"); + _ChronoParts __needed = _ChronoParts::_None; + bool __locale_specific = false; - // Scan for next '%', ignoring literal-chars before it. - size_t __pos = __string_view(__first, __last - __first).find('%'); - if (__pos == 0) - ++__first; - else - { - if (__pos == __string_view::npos) - { - __first = __last; - __conv = false; - } - else - __first += __pos + 1; - } + _CharT __c = *__first++; + switch (__c) + { + using enum _ChronoParts; + case 'a': + case 'A': + __needed = _Weekday; + __locale_specific = true; + break; + case 'b': + case 'h': + case 'B': + __needed = _Month; + __locale_specific = true; + break; + case 'c': + __needed = _Date|_HoursMinutesSeconds; + __allowed_mods = _Mod_E; + __locale_specific = true; + break; + case 'C': + __needed = _Year; + __allowed_mods = _Mod_E; + break; + case 'd': + case 'e': + __needed = _Day; + __allowed_mods = _Mod_O; + break; + case 'D': + case 'F': + __needed = _YearMonthDay; + break; + case 'g': + case 'G': + case 'V': + __needed = _LocalDays|_Year|_DayOfYear|_Weekday; + break; + case 'H': + case 'I': + __needed = _HoursMinutesSeconds; + __allowed_mods = _Mod_O; + break; + case 'j': + __needed = __parts & _DayOfYear; + // If we do not know day-of-year then we must have a duration, + // which is to be formatted as decimal number of days. + if (__needed == _None) + __needed = _HoursMinutesSeconds; + break; + case 'm': + __needed = _Month; + __allowed_mods = _Mod_O; + break; + case 'M': + __needed = _HoursMinutesSeconds; + __allowed_mods = _Mod_O; + break; + case 'p': + case 'r': + __locale_specific = true; + [[fallthrough]]; + case 'R': + __needed = _HoursMinutesSeconds; + break; + case 'T': + __needed = _TimeOfDay; + break; + case 'q': + __needed = _UnitSuffix; + break; + case 'Q': + __needed = _EpochUnits; + break; + case 'S': + __needed = _TimeOfDay; + __allowed_mods = _Mod_O; + break; + case 'u': + case 'w': + __needed = _Weekday; + __allowed_mods = _Mod_O; + break; + case 'U': + case 'W': + __needed = _DayOfYear|_Weekday; + __allowed_mods = _Mod_O; + break; + case 'x': + __needed = _Date; + __locale_specific = true; + __allowed_mods = _Mod_E; + break; + case 'X': + __needed = _HoursMinutesSeconds; + __locale_specific = true; + __allowed_mods = _Mod_E; + break; + case 'y': + __needed = _Year; + __allowed_mods = _Mod_E_O; + break; + case 'Y': + __needed = _Year; + __allowed_mods = _Mod_E; + break; + case 'z': + __needed = _ZoneOffset; + __allowed_mods = _Mod_E_O; + break; + case 'Z': + __needed = _ZoneAbbrev; + break; + case 'n': + case 't': + case '%': + break; + case 'O': + case 'E': + if (__mod) [[unlikely]] + { + __allowed_mods = _Mod_none; + break; + } + __mod = __c; + continue; + default: + __throw_format_error("chrono format error: invalid specifier " + "in chrono-specs"); } - // Check for a '%' conversion-spec without a type. - if (__conv || __mod != _CharT()) - __throw_format_error("chrono format error: unescaped '%' in " - "chrono-specs"); + if ((__mod == 'E' && !(__allowed_mods & _Mod_E)) + || (__mod == 'O' && !(__allowed_mods & _Mod_O))) + __throw_format_error("chrono format error: invalid modifier " + "in chrono-specs"); + if (__mod && __c != 'z') + __locale_specific = true; + __mod = _CharT(); + + // localized formats do not include subseconds + if (__locale_specific) + __needed -= _ChronoParts::_Subseconds; + + if ((__parts & __needed) != __needed) + __throw_format_error("chrono format error: format argument does " + "not contain the information required by the " + "chrono-specs"); + __spec._M_needed |= __needed; + __spec._M_locale_specific |= __locale_specific; + + // Scan for next '%', ignoring literal-chars before it. + size_t __pos = __string_view(__first, __last - __first).find('%'); + if (__pos == 0) + ++__first; + else + { + if (__pos == __string_view::npos) + { + __first = __last; + __conv = false; + } + else + __first += __pos + 1; + } + } + + // Check for a '%' conversion-spec without a type. + if (__conv || __mod != _CharT()) + __throw_format_error("chrono format error: unescaped '%' in " + "chrono-specs"); - _M_spec = __spec; - _M_spec._M_chrono_specs - = __string_view(__chrono_specs, __first - __chrono_specs); - _M_spec._M_locale_specific(__locale_specific); + __spec._M_chrono_specs + = __string_view(__chrono_specs, __first - __chrono_specs); - return __first; - } + __finalize(); + return __first; + } - // TODO this function template is instantiated for every different _Tp. - // Consider creating a polymorphic interface for calendar types so - // that we instantiate fewer different specializations. Similar to - // _Sink_iter for std::format. Replace each _S_year, _S_day etc. with - // member functions of that type. - template<typename _Tp, typename _FormatContext> + // pre: !_M_spec._M_chrono_specs.empty() + template<typename _FormatContext> typename _FormatContext::iterator - _M_format(const _Tp& __t, _FormatContext& __fc, - bool __is_neg = false) const + _M_format(const _ChronoData<_CharT>& __t, _FormatContext& __fc) const { - if (_M_spec._M_chrono_specs.empty()) - return _M_format_to_ostream(__t, __fc, __is_neg); - #if defined _GLIBCXX_USE_NL_LANGINFO_L && __CHAR_BIT__ == 8 // _GLIBCXX_RESOLVE_LIB_DEFECTS // 3565. Handling of encodings in localized formatting // of chrono types is underspecified if constexpr (is_same_v<_CharT, char>) if constexpr (__unicode::__literal_encoding_is_utf8()) - if (_M_spec._M_localized && _M_spec._M_locale_specific()) + if (_M_spec._M_localized && _M_spec._M_locale_specific) { extern locale __with_encoding_conversion(const locale&); @@ -520,36 +856,207 @@ namespace __format // in the locale's encoding to UTF-8. locale __loc = __fc.locale(); if (__loc != locale::classic()) - __fc._M_loc = __with_encoding_conversion(__loc); + __fc._M_loc = __with_encoding_conversion(__loc); } #endif - // formatter<duration> passes the correct value of __is_neg - // for durations but for hh_mm_ss we decide it here. - if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>) - __is_neg = __t.is_negative(); const size_t __padwidth = _M_spec._M_get_width(__fc); if (__padwidth == 0) - return _M_format_to(__t, __fc.out(), __fc, __is_neg); + return _M_format_to(__t, __fc.out(), __fc); using _Out = typename _FormatContext::iterator; _Padding_sink<_Out, _CharT> __sink(__fc.out(), __padwidth); - _M_format_to(__t, __sink.out(), __fc, __is_neg); + _M_format_to(__t, __sink.out(), __fc); return __sink._M_finish(_M_spec._M_align, _M_spec._M_fill); } - template<typename _Tp, typename _Out, typename _FormatContext> - _Out - _M_format_to(const _Tp& __t, _Out __out, _FormatContext& __fc, - bool __is_neg) const + _ChronoSpec<_CharT> _M_spec; + + protected: + static constexpr const _CharT* _S_chars + = _GLIBCXX_WIDEN("0123456789.Lf:/ +-{}"); + static constexpr _CharT _S_dot = _S_chars[10]; + static constexpr _CharT _S_colon = _S_chars[13]; + static constexpr _CharT _S_slash = _S_chars[14]; + static constexpr _CharT _S_space = _S_chars[15]; + static constexpr const _CharT* _S_fp_fmt = _S_chars + 11; + static constexpr const _CharT* _S_plus_minus = _S_chars + 16; + static constexpr const _CharT* _S_minus_empty_spec = _S_chars + 17; + static constexpr const _CharT* _S_empty_spec = _S_chars + 18; + + [[__gnu__::__always_inline__]] + static _Runtime_format_string<_CharT> + _S_empty_fs() + { return _Runtime_format_string<_CharT>(_S_empty_spec); } + + static constexpr const _CharT* _S_weekdays[] + { + _GLIBCXX_WIDEN("Sunday"), + _GLIBCXX_WIDEN("Monday"), + _GLIBCXX_WIDEN("Tuesday"), + _GLIBCXX_WIDEN("Wednesday"), + _GLIBCXX_WIDEN("Thursday"), + _GLIBCXX_WIDEN("Friday"), + _GLIBCXX_WIDEN("Saturday"), + }; + + static constexpr const _CharT* _S_months[] + { + _GLIBCXX_WIDEN("January"), + _GLIBCXX_WIDEN("February"), + _GLIBCXX_WIDEN("March"), + _GLIBCXX_WIDEN("April"), + _GLIBCXX_WIDEN("May"), + _GLIBCXX_WIDEN("June"), + _GLIBCXX_WIDEN("July"), + _GLIBCXX_WIDEN("August"), + _GLIBCXX_WIDEN("September"), + _GLIBCXX_WIDEN("October"), + _GLIBCXX_WIDEN("November"), + _GLIBCXX_WIDEN("December"), + }; + + private: + template<typename _OutIter> + _OutIter + _M_write(_OutIter __out, const locale& __loc, __string_view __s) const + { +#if defined _GLIBCXX_USE_NL_LANGINFO_L && __CHAR_BIT__ == 8 + __sso_string __buf; + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3565. Handling of encodings in localized formatting + // of chrono types is underspecified + if constexpr (is_same_v<_CharT, char>) + if constexpr (__unicode::__literal_encoding_is_utf8()) + if (_M_spec._M_localized && _M_spec._M_locale_specific + && __loc != locale::classic()) + { + extern string_view + __locale_encoding_to_utf8(const locale&, string_view, void*); + + __s = __locale_encoding_to_utf8(__loc, __s, &__buf); + } +#endif + return __format::__write(std::move(__out), __s); + } + + [[__gnu__::__always_inline__]] + static bool + _S_localized_spec(_CharT __conv, _CharT __mod) + { + switch (__conv) + { + case 'a': + case 'A': + case 'b': + case 'B': + case 'c': + case 'h': + case 'p': + case 'r': + case 'x': + case 'X': + return true; + case 'z': + return false; + default: + return (bool)__mod; + }; + } + + // Use the formatting locale's std::time_put facet to produce + // a locale-specific representation. + template<typename _Iter> + _Iter + _M_locale_fmt(_Iter __out, const locale& __loc, const struct tm& __tm, + char __fmt, char __mod) const + { + basic_ostringstream<_CharT> __os; + __os.imbue(__loc); + const auto& __tp = use_facet<time_put<_CharT>>(__loc); + __tp.put(__os, __os, _S_space, &__tm, __fmt, __mod); + if (__os) + __out = _M_write(std::move(__out), __loc, __os.view()); + return __out; + } + + __string_view + _M_check_ok(const _ChronoData<_CharT>& __t, _CharT& __conv) const + { + if (!_M_spec._M_debug) + { + switch (__conv) + { + case 'a': + case 'A': + if (!__t._M_weekday.ok()) [[unlikely]] + __throw_format_error("format error: invalid weekday"); + break; + case 'b': + case 'h': + case 'B': + if (!__t._M_month.ok()) [[unlikely]] + __throw_format_error("format error: invalid month"); + break; + default: + break; + } + return __string_view(); + } + + switch (__conv) + { + // %\0 is extension for handling weekday index + case '\0': + if (__t._M_weekday_index < 1 || __t._M_weekday_index > 5) [[unlikely]] + return _GLIBCXX_WIDEN("index"); + break; + case 'a': + case 'A': + if (!__t._M_weekday.ok()) [[unlikely]] + { + __conv = 'w'; // print as decimal number + return _GLIBCXX_WIDEN("weekday"); + } + break; + case 'b': + case 'h': + case 'B': + if (!__t._M_month.ok()) [[unlikely]] + { + __conv = 'm'; // print as decimal number + return _GLIBCXX_WIDEN("month"); + } + break; + case 'd': + case 'e': + if (!__t._M_day.ok()) [[unlikely]] + return _GLIBCXX_WIDEN("day"); + break; + case 'F': + if (!(__t._M_year/__t._M_month/__t._M_day).ok()) [[unlikely]] + return _GLIBCXX_WIDEN("date"); + break; + case 'Y': + if (!__t._M_year.ok()) [[unlikely]] + return _GLIBCXX_WIDEN("year"); + break; + default: + break; + } + return __string_view(); + } + + template<typename _OutIter, typename _FormatContext> + _OutIter + _M_format_to(const _ChronoData<_CharT>& __t, _OutIter __out, + _FormatContext& __fc) const { auto __first = _M_spec._M_chrono_specs.begin(); const auto __last = _M_spec._M_chrono_specs.end(); - auto __print_sign = [&__is_neg, &__out] { - if constexpr (chrono::__is_duration_v<_Tp> - || __is_specialization_of<_Tp, chrono::hh_mm_ss>) - if (__is_neg) + auto __print_sign = [__is_neg = __t._M_is_neg, &__out] () mutable { + if (__is_neg) { *__out++ = _S_plus_minus[1]; __is_neg = false; @@ -557,6 +1064,36 @@ namespace __format return std::move(__out); }; + struct tm __tm{}; + bool __use_locale_fmt = false; + if (_M_spec._M_localized && _M_spec._M_locale_specific) + if (__fc.locale() != locale::classic()) + { + __use_locale_fmt = true; + + __tm.tm_year = (int)__t._M_year - 1900; + __tm.tm_yday = __t._M_day_of_year.count(); + __tm.tm_mon = (unsigned)__t._M_month - 1; + __tm.tm_mday = (unsigned)__t._M_day; + __tm.tm_wday = __t._M_weekday.c_encoding(); + __tm.tm_hour = __t._M_hours.count(); + __tm.tm_min = __t._M_minutes.count(); + __tm.tm_sec = __t._M_seconds.count(); + + // Some locales use %Z in their %c format but we don't want strftime + // to use the system's local time zone (from /etc/localtime or $TZ) + // as the output for %Z. Setting tm_isdst to -1 says there is no + // time zone info available for the time in __tm. + __tm.tm_isdst = -1; + +#ifdef _GLIBCXX_USE_STRUCT_TM_TM_ZONE + // POSIX.1-2024 adds tm.tm_zone which will be used for %Z. + // BSD has had tm_zone since 1987 but as char* so cast away const. + if (__t._M_zone_cstr) + __tm.tm_zone = const_cast<char*>(__t._M_zone_cstr); +#endif + } + // Characters to output for "%n", "%t" and "%%" specifiers. constexpr const _CharT* __literals = _GLIBCXX_WIDEN("\n\t%"); @@ -566,100 +1103,101 @@ namespace __format do { _CharT __c = *__first++; - switch (__c) + __string_view __invalid; + if (_M_spec._M_needs_ok_check) + __invalid = _M_check_ok(__t, __c); + + if (__invalid.empty() &&__use_locale_fmt + && _S_localized_spec(__c, __mod)) [[unlikely]] + __out = _M_locale_fmt(std::move(__out), __fc.locale(), + __tm, __c, __mod); + else switch (__c) { + // %\0 is extension for handling weekday index + case '\0': + __out = _M_wi(__t._M_weekday_index, std::move(__out)); + break; case 'a': case 'A': - __out = _M_a_A(__t, std::move(__out), __fc, __c == 'A'); + __out = _M_a_A(__t._M_weekday, std::move(__out), __c == 'A'); break; case 'b': case 'h': case 'B': - __out = _M_b_B(__t, std::move(__out), __fc, __c == 'B'); + __out = _M_b_B(__t._M_month, std::move(__out), __c == 'B'); break; case 'c': - __out = _M_c(__t, std::move(__out), __fc, __mod == 'E'); + __out = _M_c(__t, std::move(__out)); break; case 'C': case 'y': case 'Y': - __out = _M_C_y_Y(__t, std::move(__out), __fc, __c, __mod); + __out = _M_C_y_Y(__t._M_year, std::move(__out), __c); break; case 'd': case 'e': - __out = _M_d_e(__t, std::move(__out), __fc, __c, __mod == 'O'); + __out = _M_d_e(__t._M_day, std::move(__out), __c); break; case 'D': - __out = _M_D(__t, std::move(__out), __fc); + case 'x': + __out = _M_D_x(__t, std::move(__out)); break; case 'F': - __out = _M_F(__t, std::move(__out), __fc); + __out = _M_F(__t, std::move(__out)); break; case 'g': case 'G': - __out = _M_g_G(__t, std::move(__out), __fc, __c == 'G'); + case 'V': + __out = _M_g_G_V(__t, std::move(__out), __c); break; case 'H': case 'I': - __out = _M_H_I(__t, __print_sign(), __fc, __c, __mod == 'O'); + __out = _M_H_I(__t._M_hours, __print_sign(), __c); break; case 'j': - __out = _M_j(__t, __print_sign(), __fc); + __out = _M_j(__t, __print_sign()); break; case 'm': - __out = _M_m(__t, std::move(__out), __fc, __mod == 'O'); + __out = _M_m(__t._M_month, std::move(__out)); break; case 'M': - __out = _M_M(__t, __print_sign(), __fc, __mod == 'O'); + __out = _M_M(__t._M_minutes, __print_sign()); break; case 'p': - __out = _M_p(__t, std::move(__out), __fc); + __out = _M_p(__t._M_hours, std::move(__out)); break; case 'q': - __out = _M_q(__t, std::move(__out), __fc); + __out = _M_q(__t._M_unit_suffix, std::move(__out)); break; case 'Q': - // %Q The duration's numeric value. - if constexpr (chrono::__is_duration_v<_Tp>) - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 4118. How should duration formatters format custom rep? - __out = std::format_to(__print_sign(), _S_empty_spec, - +__t.count()); - else - __throw_format_error("chrono format error: argument is " - "not a duration"); + __out = _M_Q(__t, __print_sign(), __fc); break; case 'r': - __out = _M_r(__t, __print_sign(), __fc); + __out = _M_r(__t, __print_sign()); break; case 'R': + case 'X': + __out = _M_R_X(__t, __print_sign(), __c != 'R'); + break; case 'T': - __out = _M_R_T(__t, __print_sign(), __fc, __c == 'T'); + __out = _M_T(__t, __print_sign(), __fc); break; case 'S': - __out = _M_S(__t, __print_sign(), __fc, __mod == 'O'); + __out = _M_S(__t, __print_sign(), __fc, __mod != 'O'); break; case 'u': case 'w': - __out = _M_u_w(__t, std::move(__out), __fc, __c, __mod == 'O'); + __out = _M_u_w(__t._M_weekday, std::move(__out), __c); break; case 'U': - case 'V': case 'W': - __out = _M_U_V_W(__t, std::move(__out), __fc, __c, - __mod == 'O'); - break; - case 'x': - __out = _M_x(__t, std::move(__out), __fc, __mod == 'E'); - break; - case 'X': - __out = _M_X(__t, __print_sign(), __fc, __mod == 'E'); + __out = _M_U_W(__t, std::move(__out), __c); break; case 'z': - __out = _M_z(__t, std::move(__out), __fc, (bool)__mod); + __out = _M_z(__t._M_zone_offset, std::move(__out), (bool)__mod); break; case 'Z': - __out = _M_Z(__t, std::move(__out), __fc); + __out = _M_Z(__t._M_zone_abbrev, std::move(__out)); break; case 'n': *__out++ = __literals[0]; @@ -678,6 +1216,14 @@ namespace __format __first = __last; break; } + + if (!__invalid.empty()) + { + constexpr __string_view __pref = _GLIBCXX_WIDEN(" is not a valid "); + __out = __format::__write(std::move(__out), __pref); + __out = __format::__write(std::move(__out), __invalid); + } + __mod = _CharT(); // Scan for next '%' and write out everything before it. __string_view __str(__first, __last - __first); @@ -700,230 +1246,61 @@ namespace __format return std::move(__out); } - _ChronoSpec<_CharT> _M_spec; - - private: - // Return the formatting locale. - template<typename _FormatContext> - std::locale - _M_locale(_FormatContext& __fc) const - { - if (!_M_spec._M_localized) - return std::locale::classic(); - else - return __fc.locale(); - } - - // Format for empty chrono-specs, e.g. "{}" (C++20 [time.format] p6). - // TODO: consider moving body of every operator<< into this function - // and use std::format("{}", t) to implement those operators. That - // would avoid std::format("{}", t) calling operator<< which calls - // std::format again. - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_format_to_ostream(const _Tp& __t, _FormatContext& __fc, - bool __is_neg) const - { - using ::std::chrono::__detail::__utc_leap_second; - using ::std::chrono::__detail::__local_time_fmt; - - basic_ostringstream<_CharT> __os; - __os.imbue(_M_locale(__fc)); - - if constexpr (__is_specialization_of<_Tp, __local_time_fmt>) - { - // Format as "{:L%F %T}" - auto __days = chrono::floor<chrono::days>(__t._M_time); - __os << chrono::year_month_day(__days) << ' ' - << chrono::hh_mm_ss(__t._M_time - __days); - - // For __local_time_fmt the __is_neg flags says whether to - // append " %Z" to the result. - if (__is_neg) - { - if (!__t._M_abbrev) [[unlikely]] - __format::__no_timezone_available(); - else if constexpr (is_same_v<_CharT, char>) - __os << ' ' << *__t._M_abbrev; - else - { - __os << L' '; - for (char __c : *__t._M_abbrev) - __os << __c; - } - } - } - else - { - if constexpr (__is_specialization_of<_Tp, __utc_leap_second>) - __os << __t._M_date << ' ' << __t._M_time; - else if constexpr (chrono::__is_time_point_v<_Tp>) - { - // Need to be careful here because not all specializations - // of chrono::sys_time can be written to an ostream. - // For the specializations of time_point that can be - // formatted with an empty chrono-specs, either it's a - // sys_time with period greater or equal to days: - if constexpr (is_convertible_v<_Tp, chrono::sys_days>) - __os << _S_date(__t); - else // Or it's formatted as "{:L%F %T}": - { - auto __days = chrono::floor<chrono::days>(__t); - __os << chrono::year_month_day(__days) << ' ' - << chrono::hh_mm_ss(__t - __days); - } - } - else - { - if constexpr (chrono::__is_duration_v<_Tp>) - if (__is_neg) [[unlikely]] - __os << _S_plus_minus[1]; - __os << __t; - } - } - - auto __str = std::move(__os).str(); - return __format::__write_padded_as_spec(__str, __str.size(), - __fc, _M_spec); - } - - static constexpr const _CharT* _S_chars - = _GLIBCXX_WIDEN("0123456789+-:/ {}"); - static constexpr const _CharT* _S_plus_minus = _S_chars + 10; - static constexpr _CharT _S_colon = _S_chars[12]; - static constexpr _CharT _S_slash = _S_chars[13]; - static constexpr _CharT _S_space = _S_chars[14]; - static constexpr const _CharT* _S_empty_spec = _S_chars + 15; - template<typename _OutIter> _OutIter - _M_write(_OutIter __out, const locale& __loc, __string_view __s) const + _M_wi(unsigned __wi, _OutIter __out) const { -#if defined _GLIBCXX_USE_NL_LANGINFO_L && __CHAR_BIT__ == 8 - __sso_string __buf; - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 3565. Handling of encodings in localized formatting - // of chrono types is underspecified - if constexpr (is_same_v<_CharT, char>) - if constexpr (__unicode::__literal_encoding_is_utf8()) - if (_M_spec._M_localized && _M_spec._M_locale_specific() - && __loc != locale::classic()) - { - extern string_view - __locale_encoding_to_utf8(const locale&, string_view, void*); - - __s = __locale_encoding_to_utf8(__loc, __s, &__buf); - } -#endif - return __format::__write(std::move(__out), __s); + // %\0 Extension to format weekday index, used only by empty format spec + _CharT __buf[3]; + __out = __format::__write(std::move(__out), _S_str_d1(__buf, __wi)); + return std::move(__out); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_a_A(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext& __ctx, bool __full) const + template<typename _OutIter> + _OutIter + _M_a_A(chrono::weekday __wd, _OutIter __out, bool __full) const { // %a Locale's abbreviated weekday name. // %A Locale's full weekday name. - chrono::weekday __wd = _S_weekday(__t); - if (!__wd.ok()) - __throw_format_error("format error: invalid weekday"); - - locale __loc = _M_locale(__ctx); - const auto& __tp = use_facet<__timepunct<_CharT>>(__loc); - const _CharT* __days[7]; - if (__full) - __tp._M_days(__days); - else - __tp._M_days_abbreviated(__days); - __string_view __str(__days[__wd.c_encoding()]); - return _M_write(std::move(__out), __loc, __str); + __string_view __str = _S_weekdays[__wd.c_encoding()]; + if (!__full) + __str = __str.substr(0, 3); + return __format::__write(std::move(__out), __str); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_b_B(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext& __ctx, bool __full) const + template<typename _OutIter> + _OutIter + _M_b_B(chrono::month __m, _OutIter __out, bool __full) const { // %b Locale's abbreviated month name. // %B Locale's full month name. - chrono::month __m = _S_month(__t); - if (!__m.ok()) - __throw_format_error("format error: invalid month"); - locale __loc = _M_locale(__ctx); - const auto& __tp = use_facet<__timepunct<_CharT>>(__loc); - const _CharT* __months[12]; - if (__full) - __tp._M_months(__months); - else - __tp._M_months_abbreviated(__months); - __string_view __str(__months[(unsigned)__m - 1]); - return _M_write(std::move(__out), __loc, __str); + __string_view __str = _S_months[(unsigned)__m - 1]; + if (!__full) + __str = __str.substr(0, 3); + return __format::__write(std::move(__out), __str); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_c(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext& __ctx, bool __mod = false) const + template<typename _OutIter> + _OutIter + _M_c(const _ChronoData<_CharT>& __t, _OutIter __out) const { - // %c Locale's date and time representation. - // %Ec Locale's alternate date and time representation. - - using namespace chrono; - using ::std::chrono::__detail::__utc_leap_second; - using ::std::chrono::__detail::__local_time_fmt; - - struct tm __tm{}; - - // Some locales use %Z in their %c format but we don't want strftime - // to use the system's local time zone (from /etc/localtime or $TZ) - // as the output for %Z. Setting tm_isdst to -1 says there is no - // time zone info available for the time in __tm. - __tm.tm_isdst = -1; - -#ifdef _GLIBCXX_USE_STRUCT_TM_TM_ZONE - // POSIX.1-2024 adds tm.tm_zone which will be used for %Z. - // BSD has had tm_zone since 1987 but as char* so cast away const. - if constexpr (__is_time_point_v<_Tp>) - { - // One of sys_time, utc_time, or local_time. - if constexpr (!is_same_v<typename _Tp::clock, local_t>) - __tm.tm_zone = const_cast<char*>("UTC"); - } - else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>) - { - // local-time-format-t is used to provide time zone info for - // one of zoned_time, tai_time, gps_time, or local_time. - if (__t._M_abbrev) - __tm.tm_zone = const_cast<char*>(__t._M_abbrev->c_str()); - } - else - __tm.tm_zone = const_cast<char*>("UTC"); -#endif - - auto __d = _S_days(__t); // Either sys_days or local_days. - using _TDays = decltype(__d); - const year_month_day __ymd(__d); - const auto __y = __ymd.year(); - const auto __hms = _S_hms(__t); - - __tm.tm_year = (int)__y - 1900; - __tm.tm_yday = (__d - _TDays(__y/January/1)).count(); - __tm.tm_mon = (unsigned)__ymd.month() - 1; - __tm.tm_mday = (unsigned)__ymd.day(); - __tm.tm_wday = weekday(__d).c_encoding(); - __tm.tm_hour = __hms.hours().count(); - __tm.tm_min = __hms.minutes().count(); - __tm.tm_sec = __hms.seconds().count(); - - return _M_locale_fmt(std::move(__out), _M_locale(__ctx), __tm, 'c', - __mod ? 'E' : '\0'); + // %c Locale's date and time representation, for C-locale: %a %b %e %T %Y + // %Ec Locale's alternate date and time representation, for C-locale same as above + + __out = _M_a_A(__t._M_weekday, std::move(__out), false); + *__out = _S_space; + __out = _M_b_B(__t._M_month, std::move(++__out), false); + *__out = _S_space; + __out = _M_d_e(__t._M_day, std::move(++__out), 'e'); + *__out = _S_space; + __out = _M_R_X(__t, std::move(++__out), true); + *__out = _S_space; + return _M_C_y_Y(__t._M_year, std::move(++__out), 'Y'); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_C_y_Y(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext& __ctx, _CharT __conv, _CharT __mod = 0) const + template<typename _OutIter> + _OutIter + _M_C_y_Y(chrono::year __y, _OutIter __out, _CharT __conv) const { // %C Year divided by 100 using floored division. // %EC Locale's alternative preresentation of the century (era name). @@ -933,598 +1310,486 @@ namespace __format // %Y Year as a decimal number. // %EY Locale's alternative full year representation. - chrono::year __y = _S_year(__t); - - if (__mod && _M_spec._M_localized) [[unlikely]] - if (auto __loc = __ctx.locale(); __loc != locale::classic()) - { - struct tm __tm{}; - __tm.tm_year = (int)__y - 1900; - return _M_locale_fmt(std::move(__out), __loc, __tm, - __conv, __mod); - } - - basic_string<_CharT> __s; int __yi = (int)__y; const bool __is_neg = __yi < 0; __yi = __builtin_abs(__yi); + int __ci = __yi / 100; + // For floored division -123//100 is -2 and -100//100 is -1 + if (__conv == 'C' && __is_neg && (__ci * 100) != __yi) [[unlikely]] + ++__ci; - if (__conv == 'Y' || __conv == 'C') + if (__conv != 'y' && __ci >= 100) [[unlikely]] { - int __ci = __yi / 100; - if (__is_neg) [[unlikely]] + using _FmtStr = _Runtime_format_string<_CharT>; + __string_view __fs = _S_minus_empty_spec + !__is_neg; + __out = std::format_to(std::move(__out), _FmtStr(__fs), + __conv == 'C' ? __ci : __yi); + } + else + { + _CharT __buf[5]; + __buf[0] = _S_plus_minus[1]; + __string_view __sv(__buf + 3, __buf + 3); + if (__conv != 'y') { - __s.assign(1, _S_plus_minus[1]); - // For floored division -123//100 is -2 and -100//100 is -1 - if (__conv == 'C' && (__ci * 100) != __yi) - ++__ci; + _S_fill_two_digits(__buf + 1, __ci); + __sv = __string_view(__buf + !__is_neg, __buf + 3); } - if (__ci >= 100) [[unlikely]] + if (__conv != 'C') { - __s += std::format(_S_empty_spec, __ci / 100); - __ci %= 100; + _S_fill_two_digits(__buf + 3, __yi % 100); + __sv = __string_view(__sv.data(), __buf + 5); } - __s += _S_two_digits(__ci); + __out = __format::__write(std::move(__out), __sv); } - - if (__conv == 'Y' || __conv == 'y') - __s += _S_two_digits(__yi % 100); - - return __format::__write(std::move(__out), __string_view(__s)); + return __out; } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_D(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext&) const + template<typename _OutIter> + _OutIter + _M_D_x(const _ChronoData<_CharT>& __t, _OutIter __out) const { - auto __ymd = _S_date(__t); - basic_string<_CharT> __s; -#if ! _GLIBCXX_USE_CXX11_ABI - __s.reserve(8); -#endif - __s = _S_two_digits((unsigned)__ymd.month()); - __s += _S_slash; - __s += _S_two_digits((unsigned)__ymd.day()); - __s += _S_slash; - __s += _S_two_digits(__builtin_abs((int)__ymd.year()) % 100); - return __format::__write(std::move(__out), __string_view(__s)); + // %D Equivalent to %m/%d/%y + // %x Locale's date rep, for C-locale: %m/%d/%y + // %Ex Locale's alternative date representation, for C-locale same as above + + auto __di = (unsigned)__t._M_day; + auto __mi = (unsigned)__t._M_month; + auto __yi = __builtin_abs((int)__t._M_year) % 100; + + if (__mi >= 100 || __di >= 100) [[unlikely]] + { + using _FmtStr = _Runtime_format_string<_CharT>; + __string_view __fs = _GLIBCXX_WIDEN("{:02d}/{:02d}/{:02d}"); + __out = std::format_to(std::move(__out), _FmtStr(__fs), + __mi, __di, __yi); + } + else + { + _CharT __buf[8]; + __buf[2] = _S_slash; + __buf[5] = _S_slash; + __string_view __sv(__buf, __buf + 8); + + _S_fill_two_digits(__buf, __mi); + _S_fill_two_digits(__buf + 3, __di); + _S_fill_two_digits(__buf + 6, __yi); + __out = __format::__write(std::move(__out), __sv); + } + return std::move(__out); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_d_e(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext& __ctx, _CharT __conv, bool __mod = false) const + template<typename _OutIter> + _OutIter + _M_d_e(chrono::day __d, _OutIter __out, _CharT __conv) const { // %d The day of month as a decimal number. // %Od Locale's alternative representation. // %e Day of month as decimal number, padded with space. // %Oe Locale's alternative digits. - chrono::day __d = _S_day(__t); unsigned __i = (unsigned)__d; - if (__mod && _M_spec._M_localized) [[unlikely]] - if (auto __loc = __ctx.locale(); __loc != locale::classic()) - { - struct tm __tm{}; - __tm.tm_mday = __i; - return _M_locale_fmt(std::move(__out), __loc, __tm, - (char)__conv, 'O'); - } - - auto __sv = _S_two_digits(__i); - _CharT __buf[2]; + _CharT __buf[3]; + auto __sv = _S_str_d2(__buf, __i); if (__conv == _CharT('e') && __i < 10) { - __buf[0] = _S_space; __buf[1] = __sv[1]; + __buf[0] = _S_space; __sv = {__buf, 2}; } - return __format::__write(std::move(__out), __sv); + + __out = __format::__write(std::move(__out), __sv); + return std::move(__out); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_F(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext&) const + template<typename _OutIter> + _OutIter + _M_F(const _ChronoData<_CharT>& __t, _OutIter __out) const { - auto __ymd = _S_date(__t); - auto __s = std::format(_GLIBCXX_WIDEN("{:04d}- - "), - (int)__ymd.year()); - auto __sv = _S_two_digits((unsigned)__ymd.month()); - __s[__s.size() - 5] = __sv[0]; - __s[__s.size() - 4] = __sv[1]; - __sv = _S_two_digits((unsigned)__ymd.day()); - __s[__s.size() - 2] = __sv[0]; - __s[__s.size() - 1] = __sv[1]; - __sv = __s; - return __format::__write(std::move(__out), __sv); + auto __di = (unsigned)__t._M_day; + auto __mi = (unsigned)__t._M_month; + auto __yi = (int)__t._M_year; + const bool __is_neg = __yi < 0; + __yi = __builtin_abs(__yi); + + if (__yi >= 10000 || __mi >= 100 || __di >= 100) [[unlikely]] + { + using _FmtStr = _Runtime_format_string<_CharT>; + __string_view __fs + = _GLIBCXX_WIDEN("-{:04d}-{:02d}-{:02d}") + !__is_neg; + __out = std::format_to(std::move(__out), _FmtStr(__fs), + __yi, __mi, __di); + } + else + { + _CharT __buf[11]; + __buf[0] = _S_plus_minus[1]; + __buf[5] = _S_plus_minus[1]; + __buf[8] = _S_plus_minus[1]; + __string_view __sv(__buf + !__is_neg, __buf + 11); + + _S_fill_two_digits(__buf + 1, __yi / 100); + _S_fill_two_digits(__buf + 3, __yi % 100); + _S_fill_two_digits(__buf + 6, __mi); + _S_fill_two_digits(__buf + 9, __di); + __out = __format::__write(std::move(__out), __sv); + } + + return std::move(__out); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_g_G(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext& __ctx, bool __full) const + template<typename _OutIter> + _OutIter + _M_g_G_V(const _ChronoData<_CharT>& __t, _OutIter __out, + _CharT __conv) const { - // %g last two decimal digits of the ISO week-based year. - // %G ISO week-based year. + // %g last two decimal digits of the ISO week-based year. + // %G ISO week-based year. + // %V ISO week-based week number as a decimal number. + // %OV Locale's alternative numeric rep. + + // ISO week-based year of __t is the year that contains the nearest + // Thursday. The ISO week of __t is the number of weeks since + // January 1 of that year. + using namespace chrono; - auto __d = _S_days(__t); - // Move to nearest Thursday: - __d -= (weekday(__d) - Monday) - days(3); - // ISO week-based year is the year that contains that Thursday: - year __y = year_month_day(__d).year(); - return _M_C_y_Y(__y, std::move(__out), __ctx, "yY"[__full]); + // Offset of the nearest Thursday: + const days __offset = (__t._M_weekday - Monday) - days(3); + // Nearest Thursday as local days: + const local_days __ild = __t._M_ldays - __offset; + // Day of year of nearest Thursday: + days __idoy = __t._M_day_of_year - __offset; + + // Year of nearest Thursday: + year __iyear; + if (__idoy <= days(0)) + __iyear = __t._M_year - years(1); + else if (__idoy <= days(365)) + __iyear = __t._M_year; + else if (__idoy == days(366) && __t._M_year.is_leap()) + __iyear = __t._M_year; + else if (__idoy <= days(730)) + __iyear = __t._M_year + years(1); + else [[unlikely]] + __iyear = year_month_day(__ild).year(); + + if (__conv != 'V') + return _M_C_y_Y(__iyear, std::move(__out), "yY"[__conv == 'G']); + + if (__iyear != __t._M_year) + __idoy = __ild - local_days(__iyear/January/0); + + const auto __wi = chrono::floor<weeks>(__idoy - days(1)).count() + 1; + return __format::__write(std::move(__out), _S_two_digits(__wi)); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_H_I(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext& __ctx, _CharT __conv, bool __mod = false) const + template<typename _OutIter> + _OutIter + _M_H_I(chrono::hours __h, _OutIter __out, _CharT __conv) const { // %H The hour (24-hour clock) as a decimal number. // %OH Locale's alternative representation. // %I The hour (12-hour clock) as a decimal number. // %OI Locale's alternative representation. - const auto __hms = _S_hms(__t); - int __i = __hms.hours().count(); - - if (__mod && _M_spec._M_localized) [[unlikely]] - if (auto __loc = __ctx.locale(); __loc != locale::classic()) - { - struct tm __tm{}; - __tm.tm_hour = __i; - return _M_locale_fmt(std::move(__out), __loc, __tm, - (char)__conv, 'O'); - } + int __i = __h.count(); if (__conv == _CharT('I')) { + __i %= 12; if (__i == 0) __i = 12; - else if (__i > 12) - __i -= 12; } + else if (__i >= 100) [[unlikely]] + return std::format_to(std::move(__out), _S_empty_fs(), __i); + return __format::__write(std::move(__out), _S_two_digits(__i)); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_j(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext&) const + template<typename _OutIter> + _OutIter + _M_j(const _ChronoData<_CharT>& __t, _OutIter __out) const { - if constexpr (chrono::__is_duration_v<_Tp>) - { - // Decimal number of days, without padding. - unsigned __d = chrono::duration_cast<chrono::days>(__t).count(); - return std::format_to(std::move(__out), _S_empty_spec, __d); - } - else - { - // Day of the year as a decimal number, padding with zero. - using namespace chrono; - auto __day = _S_days(__t); - auto __ymd = _S_date(__t); - days __d; - // See "Calculating Ordinal Dates" at - // https://github.com/HowardHinnant/date/wiki/Examples-and-Recipes - if constexpr (is_same_v<typename decltype(__day)::clock, local_t>) - __d = __day - local_days(__ymd.year()/January/0); - else - __d = __day - sys_days(__ymd.year()/January/0); - return std::format_to(std::move(__out), _GLIBCXX_WIDEN("{:03d}"), - __d.count()); - } + if (!_M_spec._M_needs(_ChronoParts::_DayOfYear)) + { + // Decimal number of days, without padding. + auto __d = chrono::floor<chrono::days>(__t._M_hours).count(); + return std::format_to(std::move(__out), _S_empty_fs(), __d); + } + + auto __d = __t._M_day_of_year.count(); + if (__d >= 1000) [[unlikely]] + return std::format_to(std::move(__out), _S_empty_fs(), __d); + + _CharT __buf[3]; + return __format::__write(std::move(__out), _S_str_d3(__buf, __d)); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_m(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext& __ctx, bool __mod) const + template<typename _OutIter> + _OutIter + _M_m(chrono::month __m, _OutIter __out) const { // %m month as a decimal number. // %Om Locale's alternative representation. - - auto __m = _S_month(__t); auto __i = (unsigned)__m; + if (__i == 0 && _M_spec._M_debug) [[unlikely]] + // 0 should not be padded to two digits + return __format::__write(std::move(__out), _S_digit(0)); - if (__mod && _M_spec._M_localized) [[unlikely]] // %Om - if (auto __loc = __ctx.locale(); __loc != locale::classic()) - { - struct tm __tm{}; - __tm.tm_mon = __i - 1; - return _M_locale_fmt(std::move(__out), __loc, __tm, - 'm', 'O'); - } - - return __format::__write(std::move(__out), _S_two_digits(__i)); + _CharT __buf[3]; + return __format::__write(std::move(__out), _S_str_d2(__buf, __i)); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_M(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext& __ctx, bool __mod) const + template<typename _OutIter> + _OutIter + _M_M(chrono::minutes __m, _OutIter __out) const { // %M The minute as a decimal number. // %OM Locale's alternative representation. - auto __m = _S_hms(__t).minutes(); auto __i = __m.count(); - - if (__mod && _M_spec._M_localized) [[unlikely]] // %OM - if (auto __loc = __ctx.locale(); __loc != locale::classic()) - { - struct tm __tm{}; - __tm.tm_min = __i; - return _M_locale_fmt(std::move(__out), __loc, __tm, - 'M', 'O'); - } - return __format::__write(std::move(__out), _S_two_digits(__i)); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_p(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext& __ctx) const + template<typename _OutIter> + _OutIter + _M_p(chrono::hours __h, _OutIter __out) const { // %p The locale's equivalent of the AM/PM designations. - auto __hms = _S_hms(__t); - locale __loc = _M_locale(__ctx); - const auto& __tp = use_facet<__timepunct<_CharT>>(__loc); - const _CharT* __ampm[2]; - __tp._M_am_pm(__ampm); - return _M_write(std::move(__out), __loc, - __ampm[__hms.hours().count() >= 12]); + + _CharT __buf[2]; + _S_fill_ampm(__buf, __h); + return __format::__write(std::move(__out), __string_view(__buf, 2)); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_q(const _Tp&, typename _FormatContext::iterator __out, - _FormatContext&) const + template<typename _OutIter> + _OutIter + _M_q(__string_view __us, _OutIter __out) const { // %q The duration's unit suffix - if constexpr (!chrono::__is_duration_v<_Tp>) - __throw_format_error("format error: argument is not a duration"); - else - { - namespace __d = chrono::__detail; - using period = typename _Tp::period; - return __d::__fmt_units_suffix<period, _CharT>(std::move(__out)); - } + return __format::__write(std::move(__out), __us); } - // %Q handled in _M_format + template<typename _OutIter, typename _FormatContext> + _OutIter + _M_Q(const _ChronoData<_CharT>& __t, _OutIter __out, + _FormatContext&) const + { + // %Q The duration's numeric value. + return std::vformat_to(std::move(__out), _S_empty_spec, __t._M_ereps); + } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_r(const _Tp& __tt, typename _FormatContext::iterator __out, - _FormatContext& __ctx) const + template<typename _OutIter> + _OutIter + _M_r(const _ChronoData<_CharT>& __t, _OutIter __out) const { - // %r locale's 12-hour clock time. - auto __t = _S_floor_seconds(__tt); - locale __loc = _M_locale(__ctx); - const auto& __tp = use_facet<__timepunct<_CharT>>(__loc); - const _CharT* __ampm_fmt; - __tp._M_am_pm_format(&__ampm_fmt); - basic_string<_CharT> __fmt(_S_empty_spec); - __fmt.insert(1u, 1u, _S_colon); - __fmt.insert(2u, __ampm_fmt); - using _FmtStr = _Runtime_format_string<_CharT>; - return _M_write(std::move(__out), __loc, - std::format(__loc, _FmtStr(__fmt), __t)); + // %r Locale's 12-hour clock time, for C-locale: %I:%M:%S %p + auto __hi = __t._M_hours.count() % 12; + if (__hi == 0) + __hi = 12; + + _CharT __buf[11]; + __buf[2] = _S_colon; + __buf[5] = _S_colon; + __buf[8] = _S_space; + _S_fill_two_digits(__buf, __hi); + _S_fill_two_digits(__buf + 3, __t._M_minutes.count()); + _S_fill_two_digits(__buf + 6, __t._M_seconds.count()); + _S_fill_ampm(__buf + 9, __t._M_hours); + + return __format::__write(std::move(__out), __string_view(__buf, 11)); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_R_T(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext& __ctx, bool __secs) const + template<typename _OutIter> + _OutIter + _M_R_X(const _ChronoData<_CharT>& __t, _OutIter __out, + bool __secs) const { - // %R Equivalent to %H:%M - // %T Equivalent to %H:%M:%S - auto __hms = _S_hms(__t); - - auto __s = std::format(_GLIBCXX_WIDEN("{:02d}:00"), - __hms.hours().count()); - auto __sv = _S_two_digits(__hms.minutes().count()); - __s[__s.size() - 2] = __sv[0]; - __s[__s.size() - 1] = __sv[1]; - __sv = __s; - __out = __format::__write(std::move(__out), __sv); - if (__secs) + // %R Equivalent to %H:%M + // %X Locale's time rep, for C-locale: %H:%M:%S (without subseconds) + // %EX Locale's alternative time representation, for C-locale same as above + + auto __hi = __t._M_hours.count(); + + _CharT __buf[8]; + __buf[2] = _S_colon; + __buf[5] = _S_colon; + __string_view __sv(__buf, 8); + + if (__hi >= 100) [[unlikely]] { - *__out++ = _S_colon; - __out = _M_S(__hms, std::move(__out), __ctx); + __out = std::format_to(std::move(__out), _S_empty_fs(), __hi); + __sv.remove_prefix(2); } - return __out; + else + _S_fill_two_digits(__buf, __hi); + + _S_fill_two_digits(__buf + 3, __t._M_minutes.count()); + if (__secs) + _S_fill_two_digits(__buf + 6, __t._M_seconds.count()); + else + __sv.remove_suffix(3); + + return __format::__write(std::move(__out), __sv); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_S(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext& __ctx, bool __mod = false) const + template<typename _OutIter, typename _FormatContext> + _OutIter + _M_S(const _ChronoData<_CharT>& __t, _OutIter __out, + _FormatContext& __ctx, bool __subs = true) const { // %S Seconds as a decimal number. // %OS The locale's alternative representation. - auto __hms = _S_hms(__t); - auto __s = __hms.seconds(); + auto __s = __t._M_seconds; - if (__mod) [[unlikely]] // %OS - { - if (_M_spec._M_localized) - if (auto __loc = __ctx.locale(); __loc != locale::classic()) - { - struct tm __tm{}; - __tm.tm_sec = (int)__s.count(); - return _M_locale_fmt(std::move(__out), __loc, __tm, - 'S', 'O'); - } + __out = __format::__write(std::move(__out), + _S_two_digits(__s.count())); + if (__subs) + __out = _M_subsecs(__t, std::move(__out), __ctx); + return __out; + } - // %OS formats don't include subseconds, so just format that: - return __format::__write(std::move(__out), - _S_two_digits(__s.count())); + template<typename _OutIter, typename _FormatContext> + _OutIter + _M_subsecs(const _ChronoData<_CharT>& __t, _OutIter __out, + _FormatContext& __ctx) const + { + unsigned __prec = _M_spec._M_prec_kind != _WP_none + ? _M_spec._M_get_precision(__ctx) + : _M_spec._M_prec; + if (__prec == 0) + return __out; + + _CharT __dot = _S_dot; + if (_M_spec._M_localized) [[unlikely]] + { + auto __loc = __ctx.locale(); + const auto& __np = use_facet<numpunct<_CharT>>(__loc); + __dot = __np.decimal_point(); } + *__out = __dot; + ++__out; - if constexpr (__hms.fractional_width == 0) - __out = __format::__write(std::move(__out), - _S_two_digits(__s.count())); - else + if (_M_spec._M_floating_point_rep) { - locale __loc = _M_locale(__ctx); - auto __ss = __hms.subseconds(); - using rep = typename decltype(__ss)::rep; - if constexpr (is_floating_point_v<rep>) - { - chrono::duration<rep> __fs = __s + __ss; - __out = std::format_to(std::move(__out), __loc, - _GLIBCXX_WIDEN("{:#0{}.{}Lf}"), - __fs.count(), - 3 + __hms.fractional_width, - __hms.fractional_width); - } + _Str_sink<_CharT> __sink; + if (_M_spec._M_localized && _M_spec._M_custom_rep) [[unlikely]] + std::vformat_to(__sink.out(), __ctx.locale(), + _GLIBCXX_WIDEN("{1:0.{2}Lf}"), __t._M_ereps); else - { - const auto& __np - = use_facet<numpunct<_CharT>>(__loc); - __out = __format::__write(std::move(__out), - _S_two_digits(__s.count())); - *__out++ = __np.decimal_point(); - if constexpr (is_integral_v<rep>) - __out = std::format_to(std::move(__out), - _GLIBCXX_WIDEN("{:0{}}"), - __ss.count(), - __hms.fractional_width); - else - { - auto __str = std::format(_S_empty_spec, __ss.count()); - __out = std::format_to(_GLIBCXX_WIDEN("{:0>{}s}"), - __str, - __hms.fractional_width); - } - } + std::vformat_to(__sink.out(), + _GLIBCXX_WIDEN("{1:0.{2}f}"), __t._M_ereps); + + auto __sv = __sink.view(); + // Skip leading zero and dot + __sv.remove_prefix(2); + return __format::__write(std::move(__out), __sv); } - return __out; + + constexpr unsigned __max_prec = _ChronoData<_CharT>::_S_max_prec; + constexpr typename _ChronoData<_CharT>::_Attoseconds::rep __pow10t[] + { + 1u, + 10u, 100u, 1000u, + 10'000u, 100'000u, 1000'000u, + 10'000'000u, 100'000'000u, 1000'000'000u, + 10'000'000'000u, 100'000'000'000u, 1000'000'000'000u, + 10'000'000'000'000u, 100'000'000'000'000u, 1000'000'000'000'000u, + 10'000'000'000'000'000u, 100'000'000'000'000'000u, 1000'000'000'000'000'000u, + }; + + auto __subs = __t._M_subseconds.count(); + if (__prec < __max_prec) + __subs /= __pow10t[__max_prec - __prec]; + else if (__prec > __max_prec) + __prec = __max_prec; + + using _FmtStr = _Runtime_format_string<_CharT>; + return std::format_to(__out, _FmtStr(_GLIBCXX_WIDEN("{0:0{1}}")), + __subs, __prec); } // %t handled in _M_format - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_u_w(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext& __ctx, _CharT __conv, bool __mod = false) const + template<typename _OutIter, typename _FormatContext> + _OutIter + _M_T(const _ChronoData<_CharT>& __t, _OutIter __out, + _FormatContext& __ctx) const + { + // %T Equivalent to %H:%M:%S, with subseconds + __out = _M_R_X(__t, std::move(__out), true); + return _M_subsecs(__t, std::move(__out), __ctx); + } + + template<typename _OutIter> + _OutIter + _M_u_w(chrono::weekday __wd, _OutIter __out, _CharT __conv) const { // %u ISO weekday as a decimal number (1-7), where Monday is 1. // %Ou Locale's alternative numeric rep. // %w Weekday as a decimal number (0-6), where Sunday is 0. // %Ow Locale's alternative numeric rep. - - chrono::weekday __wd = _S_weekday(__t); - - if (__mod && _M_spec._M_localized) [[unlikely]] - if (auto __loc = __ctx.locale(); __loc != locale::classic()) - { - struct tm __tm{}; - __tm.tm_wday = __wd.c_encoding(); - return _M_locale_fmt(std::move(__out), __loc, __tm, - (char)__conv, 'O'); - } - unsigned __wdi = __conv == 'u' ? __wd.iso_encoding() : __wd.c_encoding(); - const _CharT __d = _S_digit(__wdi); - return __format::__write(std::move(__out), __string_view(&__d, 1)); + _CharT __buf[3]; + return __format::__write(std::move(__out), _S_str_d1(__buf, __wdi)); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_U_V_W(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext& __ctx, _CharT __conv, bool __mod = false) const + template<typename _OutIter> + _OutIter + _M_U_W(const _ChronoData<_CharT>& __t, _OutIter __out, + _CharT __conv) const { // %U Week number of the year as a decimal number, from first Sunday. // %OU Locale's alternative numeric rep. - // %V ISO week-based week number as a decimal number. - // %OV Locale's alternative numeric rep. // %W Week number of the year as a decimal number, from first Monday. // %OW Locale's alternative numeric rep. - using namespace chrono; - auto __d = _S_days(__t); - using _TDays = decltype(__d); // Either sys_days or local_days. - - if (__mod && _M_spec._M_localized) [[unlikely]] - if (auto __loc = __ctx.locale(); __loc != locale::classic()) - { - const year_month_day __ymd(__d); - const year __y = __ymd.year(); - struct tm __tm{}; - __tm.tm_year = (int)__y - 1900; - __tm.tm_yday = (__d - _TDays(__y/January/1)).count(); - __tm.tm_wday = weekday(__d).c_encoding(); - return _M_locale_fmt(std::move(__out), __loc, __tm, - (char)__conv, 'O'); - } - - _TDays __first; // First day of week 1. - if (__conv == 'V') // W01 begins on Monday before first Thursday. - { - // Move to nearest Thursday: - __d -= (weekday(__d) - Monday) - days(3); - // ISO week of __t is number of weeks since January 1 of the - // same year as that nearest Thursday. - __first = _TDays(year_month_day(__d).year()/January/1); - } - else - { - year __y; - if constexpr (requires { __t.year(); }) - __y = __t.year(); - else - __y = year_month_day(__d).year(); - const weekday __weekstart = __conv == 'U' ? Sunday : Monday; - __first = _TDays(__y/January/__weekstart[1]); - } - auto __weeks = chrono::floor<weeks>(__d - __first); - __string_view __sv = _S_two_digits(__weeks.count() + 1); - return __format::__write(std::move(__out), __sv); - } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_x(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext& __ctx, bool __mod = false) const - { - // %x Locale's date rep - // %Ex Locale's alternative date representation. - locale __loc = _M_locale(__ctx); - const auto& __tp = use_facet<__timepunct<_CharT>>(__loc); - const _CharT* __date_reps[2]; - __tp._M_date_formats(__date_reps); - const _CharT* __rep = __date_reps[__mod]; - if (!*__rep) - return _M_D(__t, std::move(__out), __ctx); - - basic_string<_CharT> __fmt(_S_empty_spec); - __fmt.insert(1u, 1u, _S_colon); - __fmt.insert(2u, __rep); - using _FmtStr = _Runtime_format_string<_CharT>; - return _M_write(std::move(__out), __loc, - std::format(__loc, _FmtStr(__fmt), __t)); - } - - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_X(const _Tp& __tt, typename _FormatContext::iterator __out, - _FormatContext& __ctx, bool __mod = false) const - { - // %X Locale's time rep - // %EX Locale's alternative time representation. - auto __t = _S_floor_seconds(__tt); - locale __loc = _M_locale(__ctx); - const auto& __tp = use_facet<__timepunct<_CharT>>(__loc); - const _CharT* __time_reps[2]; - __tp._M_time_formats(__time_reps); - const _CharT* __rep = __time_reps[__mod]; - if (!*__rep) - return _M_R_T(__t, std::move(__out), __ctx, true); - - basic_string<_CharT> __fmt(_S_empty_spec); - __fmt.insert(1u, 1u, _S_colon); - __fmt.insert(2u, __rep); - using _FmtStr = _Runtime_format_string<_CharT>; - return _M_write(std::move(__out), __loc, - std::format(__loc, _FmtStr(__fmt), __t)); + using namespace chrono; + const weekday __weekstart = __conv == 'U' ? Sunday : Monday; + const days __offset = __t._M_weekday - __weekstart; + auto __weeks = chrono::floor<weeks>(__t._M_day_of_year - __offset - days(1)); + return __format::__write(std::move(__out), _S_two_digits(__weeks.count() + 1)); } - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_z(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext&, bool __mod = false) const + template<typename _OutIter> + _OutIter + _M_z(chrono::seconds __ts, _OutIter __out, bool __mod = false) const { - using ::std::chrono::__detail::__utc_leap_second; - using ::std::chrono::__detail::__local_time_fmt; - - auto __utc = __mod ? __string_view(_GLIBCXX_WIDEN("+00:00"), 6) - : __string_view(_GLIBCXX_WIDEN("+0000"), 5); - - if constexpr (chrono::__is_time_point_v<_Tp>) - { - if constexpr (is_same_v<typename _Tp::clock, - chrono::system_clock>) - return __format::__write(std::move(__out), __utc); - } - else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>) + if (__ts == 0s) { - if (__t._M_offset_sec) - { - auto __sv = __utc; - basic_string<_CharT> __s; - if (*__t._M_offset_sec != 0s) - { - chrono:: hh_mm_ss __hms(*__t._M_offset_sec); - __s = _S_plus_minus[__hms.is_negative()]; - __s += _S_two_digits(__hms.hours().count()); - if (__mod) - __s += _S_colon; - __s += _S_two_digits(__hms.minutes().count()); - __sv = __s; - } - return __format::__write(std::move(__out), __sv); - } + __string_view __zero + = __mod ? _GLIBCXX_WIDEN("+00:00") : _GLIBCXX_WIDEN("+0000"); + return __format::__write(std::move(__out), __zero); } - else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>) - return __format::__write(std::move(__out), __utc); - __no_timezone_available(); - } + chrono::hh_mm_ss<chrono::seconds> __hms(__ts); + unsigned __mo = 3 + __mod; - template<typename _Tp, typename _FormatContext> - typename _FormatContext::iterator - _M_Z(const _Tp& __t, typename _FormatContext::iterator __out, - _FormatContext& __ctx) const - { - using ::std::chrono::__detail::__utc_leap_second; - using ::std::chrono::__detail::__local_time_fmt; + _CharT __buf[6]; + __buf[0] = _S_plus_minus[__hms.is_negative()]; + __buf[3] = _S_colon; + _S_fill_two_digits(__buf + 1, __hms.hours().count()); + _S_fill_two_digits(__buf + __mo, __hms.minutes().count()); - __string_view __utc(_GLIBCXX_WIDEN("UTC"), 3); - if constexpr (chrono::__is_time_point_v<_Tp>) - { - if constexpr (is_same_v<typename _Tp::clock, - chrono::system_clock>) - return __format::__write(std::move(__out), __utc); - } - else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>) - { - if (__t._M_abbrev) - { - string_view __sv = *__t._M_abbrev; - if constexpr (is_same_v<_CharT, char>) - return __format::__write(std::move(__out), __sv); - else - { - // TODO use resize_and_overwrite - basic_string<_CharT> __ws(__sv.size(), _CharT()); - auto& __ct = use_facet<ctype<_CharT>>(_M_locale(__ctx)); - __ct.widen(__sv.begin(), __sv.end(), __ws.data()); - __string_view __wsv = __ws; - return __format::__write(std::move(__out), __wsv); - } - } - } - else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>) - return __format::__write(std::move(__out), __utc); - - __no_timezone_available(); + __string_view __sv(__buf, __mo + 2); + return __format::__write(std::move(__out), __sv); } + template<typename _OutIter> + _OutIter + _M_Z(__string_view __abbrev, _OutIter __out) const + { return __format::__write(std::move(__out), __abbrev); } + // %% handled in _M_format - // A single digit character in the range '0'..'9'. - static _CharT + // A string view of single digit character, "0".."9". + static basic_string_view<_CharT> _S_digit(int __n) noexcept { // Extra 9s avoid past-the-end read on bad input. - return _GLIBCXX_WIDEN("0123456789999999")[__n & 0xf]; + return { _GLIBCXX_WIDEN("0123456789999999") + (__n & 0xf), 1 }; } // A string view of two digit characters, "00".."99". @@ -1543,178 +1808,352 @@ namespace __format }; } - // Accessors for the components of chrono types: + // Fills __buf[0] and __buf[1] with 2 digit value of __n. + [[__gnu__::__always_inline__]] + static void + _S_fill_two_digits(_CharT* __buf, unsigned __n) + { + auto __sv = _S_two_digits(__n); + __buf[0] = __sv[0]; + __buf[1] = __sv[1]; + } + + // Fills __buf[0] and __buf[1] with "AM", "PM" depending on __h. + [[__gnu__::__always_inline__]] + static void + _S_fill_ampm(_CharT* __buf, chrono::hours __h) + { + auto __hi = __h.count(); + if (__hi >= 24) [[unlikely]] + __hi %= 24; + + constexpr const _CharT* __apm = _GLIBCXX_WIDEN("APM"); + __buf[0] = __apm[__hi >= 12]; + __buf[1] = __apm[2]; + } + + // Returns decimal representation of __n. + // Returned string_view may point to __buf. + [[__gnu__::__always_inline__]] + static basic_string_view<_CharT> + _S_str_d1(span<_CharT, 3> __buf, unsigned __n) + { + if (__n < 10) [[likely]] + return _S_digit(__n); + return _S_str_d2(__buf, __n); + } + + // Returns decimal representation of __n, padded to 2 digits. + // Returned string_view may point to __buf. + [[__gnu__::__always_inline__]] + static basic_string_view<_CharT> + _S_str_d2(span<_CharT, 3> __buf, unsigned __n) + { + if (__n < 100) [[likely]] + return _S_two_digits(__n); + return _S_str_d3(__buf, __n); + } + + // Returns decimal representation of __n, padded to 3 digits. + // Returned string_view points to __buf. + [[__gnu__::__always_inline__]] + static basic_string_view<_CharT> + _S_str_d3(span<_CharT, 3> __buf, unsigned __n) + { + _S_fill_two_digits(__buf.data(), __n / 10); + __buf[2] = _S_chars[__n % 10]; + return __string_view(__buf.data(), 3); + } + }; - // Returns a hh_mm_ss. - template<typename _Tp> - static decltype(auto) - _S_hms(const _Tp& __t) + template<typename _CharT> + struct __formatter_duration : private __formatter_chrono<_CharT> + { + template<typename _Rep, typename _Period> + constexpr static auto + _S_subseconds(const chrono::duration<_Rep, _Period>& __d) { - using ::std::chrono::__detail::__utc_leap_second; - using ::std::chrono::__detail::__local_time_fmt; - - if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>) - return __t; - else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>) - return __t._M_time; - else if constexpr (chrono::__is_duration_v<_Tp>) - return chrono::hh_mm_ss<_Tp>(__t); - else if constexpr (chrono::__is_time_point_v<_Tp>) - return chrono::hh_mm_ss(__t - chrono::floor<chrono::days>(__t)); - else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>) - return _S_hms(__t._M_time); + if constexpr (chrono::treat_as_floating_point_v<_Rep>) + return chrono::duration<_Rep>(__d); + else if constexpr (_Period::den == 1) + return chrono::seconds(0); else - { - __invalid_chrono_spec(); - return chrono::hh_mm_ss<chrono::seconds>(); - } - } + { + using _Attoseconds = _ChronoData<_CharT>::_Attoseconds; + using _CRep = common_type_t<_Rep, typename _Attoseconds::rep>; + chrono::duration<_CRep, _Period> subs(__d.count()); + return chrono::duration_cast<_Attoseconds>(subs); + } + } - // Returns a sys_days or local_days. - template<typename _Tp> - static auto - _S_days(const _Tp& __t) + public: + template<typename _Duration> + static consteval + _ChronoSpec<_CharT> + _S_spec_for(_ChronoParts __parts) { - using namespace chrono; - using ::std::chrono::__detail::__utc_leap_second; - using ::std::chrono::__detail::__local_time_fmt; - - if constexpr (__is_time_point_v<_Tp>) - return chrono::floor<days>(__t); - else if constexpr (__is_specialization_of<_Tp, __utc_leap_second>) - return __t._M_date; - else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>) - return chrono::floor<days>(__t._M_time); - else if constexpr (is_same_v<_Tp, year_month_day> - || is_same_v<_Tp, year_month_day_last> - || is_same_v<_Tp, year_month_weekday> - || is_same_v<_Tp, year_month_weekday_last>) - return sys_days(__t); - else + using _Rep = typename _Duration::rep; + using enum _ChronoParts; + + _ChronoSpec<_CharT> __res{}; + __res._M_floating_point_rep = chrono::treat_as_floating_point_v<_Rep>; + __res._M_custom_rep = !is_arithmetic_v<_Rep>; + __res._M_prec = chrono::hh_mm_ss<_Duration>::fractional_width; + if ((__parts & _TimeOfDay) != 0) + __res._M_localized = __res._M_prec > 0 || __res._M_floating_point_rep; + + if ((__parts & _TimeOfDay) != 0) + __res._M_needed |= _TimeOfDay; + if ((__parts & _Date) != 0) + __res._M_needed |= _YearMonthDay; + if ((__parts & _ZoneAbbrev) != 0) + __res._M_needed |= _ZoneAbbrev; + + switch (__parts) { - if constexpr (__is_duration_v<_Tp>) - __not_valid_for_duration(); - else - __invalid_chrono_spec(); - return chrono::sys_days(); + case _ZonedDateTime: + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_ftz(); + break; + case _DateTime: + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_ft(); + break; + case _Date: + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_f(); + break; + case _Time: + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_t(); + break; + case _None: + break; + default: + __builtin_unreachable(); } - } + return __res; + }; - // Returns a year_month_day. - template<typename _Tp> - static chrono::year_month_day - _S_date(const _Tp& __t) + template<typename _Duration> + static consteval + _ChronoSpec<_CharT> + _S_spec_for_tp() { - if constexpr (is_same_v<_Tp, chrono::year_month_day>) - return __t; + using enum _ChronoParts; + // streaming of local_time is defined in terms of sys_time + constexpr bool __stream_insertable = + requires (basic_ostream<_CharT>& __os, chrono::sys_time<_Duration> __t) + { __os << __t; }; + if constexpr (!__stream_insertable) + return _S_spec_for<_Duration>(_None); + else if constexpr (is_convertible_v<_Duration, chrono::days>) + return _S_spec_for<_Duration>(_Date); else - return chrono::year_month_day(_S_days(__t)); + return _S_spec_for<_Duration>(_DateTime); } - template<typename _Tp> - static chrono::day - _S_day(const _Tp& __t) + using __formatter_chrono<_CharT>::__formatter_chrono; + using __formatter_chrono<_CharT>::_M_spec; + + template<typename _Duration> + constexpr typename basic_format_parse_context<_CharT>::iterator + _M_parse(basic_format_parse_context<_CharT>& __pc, _ChronoParts __parts, + const _ChronoSpec<_CharT>& __def) { - using namespace chrono; + using _Rep = typename _Duration::rep; + using enum _ChronoParts; + + auto __res + = __formatter_chrono<_CharT>::_M_parse(__pc, __parts, __def); + // n.b. durations do not contain date parts, and for time point all + // date parts are computed, and they are always ok. + _M_spec._M_needs_ok_check = false; + + // check for custom floating point durations, if digits of output + // will contain subseconds, then formatters must support specifying + // precision. + if constexpr (!is_floating_point_v<_Rep>) + if constexpr (chrono::treat_as_floating_point_v<_Rep>) + if (_M_spec._M_needs(_Subseconds|_EpochUnits) + || _M_spec._M_prec_kind != _WP_none + || _M_spec._M_prec_value > 0) + { + constexpr const _CharT* __fs = _GLIBCXX_WIDEN("#02.5Lf"); + basic_format_parse_context<_CharT> __npc(__fs); + formatter<_Rep, _CharT> __fmtter; + __fmtter.parse(__npc); + } + return __res; + } - if constexpr (is_same_v<_Tp, day>) - return __t; - else if constexpr (requires { __t.day(); }) - return __t.day(); + // Return the formatting locale. + template<typename _FormatContext> + std::locale + _M_locale(_FormatContext& __fc) const + { + if (!_M_spec._M_localized) + return std::locale::classic(); else - return _S_date(__t).day(); + return __fc.locale(); } - template<typename _Tp> - static chrono::month - _S_month(const _Tp& __t) + // Format duration for empty chrono-specs, e.g. "{}" (C++20 [time.format] p6). + template<typename _Rep, typename _Period, typename _FormatContext> + typename _FormatContext::iterator + _M_format_to_ostream(const chrono::duration<_Rep, _Period>& __d, + bool __is_neg, + _FormatContext& __fc) const { - using namespace chrono; + basic_ostringstream<_CharT> __os; + __os.imbue(this->_M_locale(__fc)); - if constexpr (is_same_v<_Tp, month>) - return __t; - else if constexpr (requires { __t.month(); }) - return __t.month(); - else - return _S_date(__t).month(); + if (__is_neg) [[unlikely]] + __os << this->_S_plus_minus[1]; + __os << __d; + + auto __str = std::move(__os).str(); + return __format::__write_padded_as_spec(__str, __str.size(), + __fc, _M_spec); } - template<typename _Tp> - static chrono::year - _S_year(const _Tp& __t) + template<typename _Rep1, typename _Period1, + typename _Rep2, typename _Period2, + typename _FormatContext> + typename _FormatContext::iterator + _M_format_units(_ChronoData<_CharT>& __cd, + const chrono::duration<_Rep1, _Period1>& __ed, + const chrono::duration<_Rep2, _Period2>& __ss, + _FormatContext& __fc) const { - using namespace chrono; + __format::_Str_sink<_CharT> __suffix_store; + constexpr auto _S_unit_suffix + = chrono::__detail::__units_suffix<_Period1, _CharT>(); + if constexpr (!_S_unit_suffix.empty()) + __cd._M_unit_suffix = _S_unit_suffix; + else if (_M_spec._M_needs(_ChronoParts::_UnitSuffix)) + { + chrono::__detail:: + __fmt_units_suffix<_Period1, _CharT>(__suffix_store.out()); + __cd._M_unit_suffix = __suffix_store.view(); + } - if constexpr (is_same_v<_Tp, year>) - return __t; - else if constexpr (requires { __t.year(); }) - return __t.year(); - else - return _S_date(__t).year(); + const auto __prec = _M_spec._M_prec_kind != _WP_none + ? _M_spec._M_get_precision(__fc) + : _M_spec._M_prec; + + using _ErasedContext = typename _ChronoData<_CharT>::_FormatContext; + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4118. How should duration formatters format custom rep? + auto __ereps = +__ed.count(); + if (!_M_spec._M_needs(_ChronoParts::_Subseconds)) + { + auto __ssreps = 0u; + auto __args_store + = std::make_format_args<_ErasedContext>(__ereps, __ssreps, __prec); + __cd._M_ereps = __args_store; + return this->_M_format(__cd, __fc); + } + + using _Attoseconds = _ChronoData<_CharT>::_Attoseconds; + auto __nss = _S_subseconds(__ss); + __cd._M_subseconds = chrono::duration_cast<_Attoseconds>(__nss); + + auto __ssreps = __nss.count(); + auto __args_store + = std::make_format_args<_ErasedContext>(__ereps, __ssreps, __prec); + __cd._M_ereps = __args_store; + + return this->_M_format(__cd, __fc); } - template<typename _Tp> - static chrono::weekday - _S_weekday(const _Tp& __t) + // pre: __cd._M_lseconds and __cd._M_eseconds are set. + template<typename _Rep1, typename _Period1, typename _FormatContext> + typename _FormatContext::iterator + _M_format_time_point(_ChronoData<_CharT>& __cd, + const chrono::duration<_Rep1, _Period1>& __ed, + _FormatContext& __fc) const { - using namespace ::std::chrono; - using ::std::chrono::__detail::__local_time_fmt; - - if constexpr (is_same_v<_Tp, weekday>) - return __t; - else if constexpr (requires { __t.weekday(); }) - return __t.weekday(); - else if constexpr (is_same_v<_Tp, month_weekday>) - return __t.weekday_indexed().weekday(); - else if constexpr (is_same_v<_Tp, month_weekday_last>) - return __t.weekday_last().weekday(); - else - return weekday(_S_days(__t)); + auto __parts = _M_spec._M_needed - _ChronoParts::_TotalSeconds; + if ((__parts & _ChronoParts::_DateTime) != 0) + __cd._M_fill_date_time(__cd._M_lseconds, __parts); + return _M_format_units(__cd, __ed, __ed - __cd._M_eseconds, __fc); } + }; - // Remove subsecond precision from a time_point. - template<typename _Tp> - static auto - _S_floor_seconds(const _Tp& __t) +#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI + template<typename _CharT> + struct __formatter_chrono_info + { + constexpr typename basic_format_parse_context<_CharT>::iterator + parse(basic_format_parse_context<_CharT>& __pc) + { return _M_f._M_parse(__pc, _ChronoParts(), {}); } + + template<typename _Info, typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + format(const _Info& __i, + basic_format_context<_Out, _CharT>& __fc) const { - using chrono::__detail::__local_time_fmt; - if constexpr (chrono::__is_time_point_v<_Tp> - || chrono::__is_duration_v<_Tp>) - { - if constexpr (_Tp::period::den != 1) - return chrono::floor<chrono::seconds>(__t); - else - return __t; - } - else if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>) + // n.b. only acceptable chrono-spec for info is one containing + // only whitespaces and %%, that do not depend on formatted object. + if (!_M_f._M_spec._M_chrono_specs.empty()) [[unlikely]] + return _M_f._M_format(_ChronoData<_CharT>{}, __fc); + + const size_t __padwidth = _M_f._M_spec._M_get_width(__fc); + if (__padwidth == 0) + return _M_format_to(__fc.out(), __i); + + _Padding_sink<_Out, _CharT> __sink(__fc.out(), __padwidth); + _M_format_to(__sink.out(), __i); + return __sink._M_finish(_M_f._M_spec._M_align, _M_f._M_spec._M_fill); + } + + private: + template<typename _Out> + _Out + _M_format_to(_Out __out, const chrono::sys_info& __si) const + { + using _FmtStr = _Runtime_format_string<_CharT>; + // n.b. only decimal separator is locale dependent for specifiers + // used below, as sys_info uses seconds and minutes duration, the + // output is locale-independent. + constexpr auto* __fs + = _GLIBCXX_WIDEN("[{0:%F %T},{1:%F %T},{2:%T},{3:%Q%q},{0:%Z}]"); + const chrono::local_seconds __lb(__si.begin.time_since_epoch()); + return std::format_to(std::move(__out), _FmtStr(__fs), + chrono::local_time_format(__lb, &__si.abbrev), + __si.end, __si.offset, __si.save); + } + + template<typename _Out> + _Out + _M_format_to(_Out __out, const chrono::local_info& __li) const + { + *__out = _Separators<_CharT>::_S_squares()[0]; + ++__out; + if (__li.result == chrono::local_info::unique) + __out = _M_format_to(std::move(__out), __li.first); + else { - if constexpr (_Tp::fractional_width != 0) - return chrono::floor<chrono::seconds>(__t.to_duration()); + basic_string_view<_CharT> __sv; + if (__li.result == chrono::local_info::nonexistent) + __sv =_GLIBCXX_WIDEN("nonexistent"); else - return __t; + __sv = _GLIBCXX_WIDEN("ambiguous"); + __out = __format::__write(std::move(__out), __sv); + + __sv = _GLIBCXX_WIDEN(" local time between "); + __out = __format::__write(std::move(__out), __sv); + __out = _M_format_to(std::move(__out), __li.first); + + __sv = _GLIBCXX_WIDEN(" and "); + __out = __format::__write(std::move(__out), __sv); + __out = _M_format_to(std::move(__out), __li.second); } - else if constexpr (__is_specialization_of<_Tp, __local_time_fmt>) - return _S_floor_seconds(__t._M_time); - else - return __t; + *__out = _Separators<_CharT>::_S_squares()[1]; + ++__out; + return std::move(__out); } - // Use the formatting locale's std::time_put facet to produce - // a locale-specific representation. - template<typename _Iter> - _Iter - _M_locale_fmt(_Iter __out, const locale& __loc, const struct tm& __tm, - char __fmt, char __mod) const - { - basic_ostringstream<_CharT> __os; - __os.imbue(__loc); - const auto& __tp = use_facet<time_put<_CharT>>(__loc); - __tp.put(__os, __os, _S_space, &__tm, __fmt, __mod); - if (__os) - __out = _M_write(std::move(__out), __loc, __os.view()); - return __out; - } + __formatter_chrono<_CharT> _M_f; }; +#endif } // namespace __format /// @endcond @@ -1726,12 +2165,8 @@ namespace __format constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) { - using namespace __format; - auto __it = _M_f._M_parse(__pc, _Duration|_TimeOfDay); - if constexpr (!is_floating_point_v<_Rep>) - if (_M_f._M_spec._M_prec_kind != __format::_WP_none) - __throw_format_error("format error: invalid precision for duration"); - return __it; + using enum __format::_ChronoParts; + return _M_f.template _M_parse<_Duration>(__pc, _EpochTime, __defSpec); } template<typename _Out> @@ -1749,324 +2184,866 @@ namespace __format using _URep = make_unsigned_t<_Rep>; auto __ucnt = -static_cast<_URep>(__d.count()); auto __ud = chrono::duration<_URep, _Period>(__ucnt); - return _M_f._M_format(__ud, __fc, true); + return _M_format(__ud, true, __fc); } else - return _M_f._M_format(-__d, __fc, true); + return _M_format(-__d, true, __fc); } - return _M_f._M_format(__d, __fc, false); + return _M_format(__d, false, __fc); } private: - __format::__formatter_chrono<_CharT> _M_f; + using _Duration = chrono::duration<_Rep, _Period>; + + static constexpr __format::_ChronoSpec<_CharT> __defSpec = [] + { + using enum __format::_ChronoParts; + auto __res = __format::__formatter_duration<_CharT>:: + template _S_spec_for<_Duration>(_None); + __res._M_localized = !is_integral_v<_Rep>; + // n.b. for integral format output is the same as ostream output + if constexpr (is_integral_v<_Rep>) + { + __res._M_needed = _EpochUnits|_UnitSuffix; + __res._M_chrono_specs = _GLIBCXX_WIDEN("%Q%q"); + } + return __res; + }(); + + template<typename _Rep2, typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + _M_format(const chrono::duration<_Rep2, _Period>& __d, + bool __is_neg, + basic_format_context<_Out, _CharT>& __fc) const + { + using namespace chrono; + using enum __format::_ChronoParts; + if constexpr (!is_integral_v<_Rep>) + if (_M_f._M_spec._M_chrono_specs.empty()) + return _M_f._M_format_to_ostream(__d, __is_neg, __fc); + + __format::_ChronoData<_CharT> __cd; + __cd._M_is_neg = __is_neg; + auto __ts = chrono::floor<chrono::seconds>(__d); + __cd._M_eseconds = __ts; + if (_M_f._M_spec._M_needs(_HoursMinutesSeconds)) + __cd._M_fill_time(__ts); + return _M_f._M_format_units(__cd, __d, __d - __ts, __fc); + } + + __format::__formatter_duration<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4400. enable_nonlocking_formatter_optimization for durations with custom rep + template<typename _Rep, typename _Period> + constexpr bool + enable_nonlocking_formatter_optimization<chrono::duration<_Rep, _Period>> + = is_arithmetic_v<_Rep>; +#endif + template<__format::__char _CharT> struct formatter<chrono::day, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_Day); } + { + using enum __format::_ChronoParts; + return _M_f._M_parse(__pc, _Day|_WeekdayIndex, __defSpec); + } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::day& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + __format::_ChronoData<_CharT> __cd{}; + __cd._M_fill_day(__t, __defSpec._M_needed); + return _M_f._M_format(__cd, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = [] + { + using __format::_ChronoFormats; + using enum __format::_ChronoParts; + + __format::_ChronoSpec<_CharT> __res{}; + __res._M_debug = true; + __res._M_needed = _Day; + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_d(); + return __res; + }(); + + __format::__formatter_chrono<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::day> = true; +#endif + template<__format::__char _CharT> struct formatter<chrono::month, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_Month); } + { + using enum __format::_ChronoParts; + return _M_f._M_parse(__pc, _Month, __defSpec); + } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::month& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + __format::_ChronoData<_CharT> __cd{}; + __cd._M_month = __t; + return _M_f._M_format(__cd, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = [] + { + using __format::_ChronoFormats; + using enum __format::_ChronoParts; + + __format::_ChronoSpec<_CharT> __res{}; + __res._M_debug = true; + __res._M_localized = true; + __res._M_locale_specific = true; + __res._M_needed = _Month; + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_m(); + return __res; + }(); + + __format::__formatter_chrono<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::month> = true; +#endif + template<__format::__char _CharT> struct formatter<chrono::year, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_Year); } + { + using enum __format::_ChronoParts; + return _M_f._M_parse(__pc, _Year, __defSpec); + } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::year& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + __format::_ChronoData<_CharT> __cd{}; + __cd._M_year = __t; + return _M_f._M_format(__cd, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = [] + { + using __format::_ChronoFormats; + using enum __format::_ChronoParts; + + __format::_ChronoSpec<_CharT> __res{}; + __res._M_debug = true; + __res._M_needed = _Year; + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_y(); + return __res; + }(); + + __format::__formatter_chrono<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::year> = true; +#endif + template<__format::__char _CharT> struct formatter<chrono::weekday, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_Weekday); } + { + using enum __format::_ChronoParts; + return _M_f._M_parse(__pc, _Weekday, __defSpec); + } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::weekday& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + __format::_ChronoData<_CharT> __cd{}; + __cd._M_weekday = __t; + return _M_f._M_format(__cd, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = [] + { + using __format::_ChronoFormats; + using enum __format::_ChronoParts; + + __format::_ChronoSpec<_CharT> __res{}; + __res._M_debug = true; + __res._M_localized = true; + __res._M_locale_specific = true; + __res._M_needed = _Weekday; + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_w(); + return __res; + }(); + + __format::__formatter_chrono<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::weekday> = true; +#endif + template<__format::__char _CharT> struct formatter<chrono::weekday_indexed, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_Weekday); } + { + using enum __format::_ChronoParts; + return _M_f._M_parse(__pc, _IndexedWeekday, __defSpec); + } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::weekday_indexed& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + __format::_ChronoData<_CharT> __cd{}; + __cd._M_fill_weekday(__t, __defSpec._M_needed); + return _M_f._M_format(__cd, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = [] + { + using __format::_ChronoFormats; + using enum __format::_ChronoParts; + + __format::_ChronoSpec<_CharT> __res{}; + __res._M_debug = true; + __res._M_localized = true; + __res._M_locale_specific = true; + __res._M_needed = _IndexedWeekday; + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_wi(); + return __res; + }(); + + __format::__formatter_chrono<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::weekday_indexed> = true; +#endif + template<__format::__char _CharT> struct formatter<chrono::weekday_last, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_Weekday); } + { + using enum __format::_ChronoParts; + return _M_f._M_parse(__pc, _Weekday, __defSpec); + } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::weekday_last& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + __format::_ChronoData<_CharT> __cd{}; + __cd._M_weekday = __t.weekday(); + return _M_f._M_format(__cd, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = [] + { + using __format::_ChronoFormats; + using enum __format::_ChronoParts; + + __format::_ChronoSpec<_CharT> __res{}; + __res._M_debug = true; + __res._M_localized = true; + __res._M_locale_specific = true; + __res._M_needed = _Weekday; + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_wl(); + return __res; + }(); + + __format::__formatter_chrono<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::weekday_last> = true; +#endif + template<__format::__char _CharT> struct formatter<chrono::month_day, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_Month|__format::_Day); } + { + using enum __format::_ChronoParts; + return _M_f._M_parse(__pc, _Month|_Day|_WeekdayIndex, __defSpec); + } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::month_day& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + __format::_ChronoData<_CharT> __cd{}; + __cd._M_month = __t.month(); + __cd._M_fill_day(__t.day(), __defSpec._M_needed); + return _M_f._M_format(__cd, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = [] + { + using __format::_ChronoFormats; + using enum __format::_ChronoParts; + + __format::_ChronoSpec<_CharT> __res{}; + __res._M_debug = true; + __res._M_localized = true; + __res._M_locale_specific = true; + __res._M_needed = _Month|_Day; + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_md(); + return __res; + }(); + + __format::__formatter_chrono<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::month_day> = true; +#endif + template<__format::__char _CharT> struct formatter<chrono::month_day_last, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_Month|__format::_Day); } + { + using enum __format::_ChronoParts; + return _M_f._M_parse(__pc, _Month, __defSpec); + } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::month_day_last& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + __format::_ChronoData<_CharT> __cd{}; + __cd._M_month = __t.month(); + return _M_f._M_format(__cd, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = [] + { + using __format::_ChronoFormats; + using enum __format::_ChronoParts; + + __format::_ChronoSpec<_CharT> __res{}; + __res._M_debug = true; + __res._M_localized = true; + __res._M_locale_specific = true; + __res._M_needed = _Month; + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_ml(); + return __res; + }(); + + __format::__formatter_chrono<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::month_day_last> = true; +#endif + template<__format::__char _CharT> struct formatter<chrono::month_weekday, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday); } + { + using enum __format::_ChronoParts; + return _M_f._M_parse(__pc, _Month|_IndexedWeekday, __defSpec); + } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::month_weekday& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + __format::_ChronoData<_CharT> __cd{}; + __cd._M_month = __t.month(); + __cd._M_fill_weekday(__t.weekday_indexed(), __defSpec._M_needed); + return _M_f._M_format(__cd, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = [] + { + using __format::_ChronoFormats; + using enum __format::_ChronoParts; + + __format::_ChronoSpec<_CharT> __res{}; + __res._M_debug = true; + __res._M_localized = true; + __res._M_locale_specific = true; + __res._M_needed = _Month|_IndexedWeekday; + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_mwi(); + return __res; + }(); + + __format::__formatter_chrono<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::month_weekday> = true; +#endif + template<__format::__char _CharT> struct formatter<chrono::month_weekday_last, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday); } + { + using enum __format::_ChronoParts; + return _M_f._M_parse(__pc, _Month|_Weekday, __defSpec); + } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::month_weekday_last& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + __format::_ChronoData<_CharT> __cd{}; + __cd._M_month = __t.month(); + __cd._M_weekday = __t.weekday_last().weekday(); + return _M_f._M_format(__cd, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = [] + { + using __format::_ChronoFormats; + using enum __format::_ChronoParts; + + __format::_ChronoSpec<_CharT> __res{}; + __res._M_debug = true; + __res._M_localized = true; + __res._M_locale_specific = true; + __res._M_needed = _Month|_Weekday; + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_mwl(); + return __res; + }(); + + __format::__formatter_chrono<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::month_weekday_last> = true; +#endif + template<__format::__char _CharT> struct formatter<chrono::year_month, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_Year|__format::_Month); } + { + using enum __format::_ChronoParts; + return _M_f._M_parse(__pc, _Year|_Month, __defSpec); + } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::year_month& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + __format::_ChronoData<_CharT> __cd{}; + __cd._M_fill_year_month(__t, __defSpec._M_needed); + return _M_f._M_format(__cd, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = [] + { + using __format::_ChronoFormats; + using enum __format::_ChronoParts; + + __format::_ChronoSpec<_CharT> __res{}; + __res._M_debug = true; + __res._M_localized = true; + __res._M_locale_specific = true; + __res._M_needed = _Year|_Month; + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_ym(); + return __res; + }(); + + __format::__formatter_chrono<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::year_month> = true; +#endif + template<__format::__char _CharT> struct formatter<chrono::year_month_day, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_Date); } + { + using enum __format::_ChronoParts; + return _M_f._M_parse(__pc, _Date, __defSpec); + } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::year_month_day& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + __format::_ChronoData<_CharT> __cd{}; + auto __parts = _M_f._M_spec._M_needed; + __parts = __cd._M_fill_year_month(__t, __parts); + __parts = __cd._M_fill_day(__t.day(), __parts); + if (__parts == 0) + return _M_f._M_format(__cd, __fc); + + __cd._M_fill_ldays(chrono::local_days(__t), __parts); + return _M_f._M_format(__cd, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = [] + { + using __format::_ChronoFormats; + using enum __format::_ChronoParts; + + __format::_ChronoSpec<_CharT> __res{}; + __res._M_debug = true; + __res._M_needed = _YearMonthDay; + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_f(); + return __res; + }(); + + __format::__formatter_chrono<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::year_month_day> = true; +#endif + template<__format::__char _CharT> struct formatter<chrono::year_month_day_last, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_Date); } + { + using enum __format::_ChronoParts; + return _M_f._M_parse(__pc, _Date, __defSpec); + } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::year_month_day_last& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + using enum __format::_ChronoParts; + + __format::_ChronoData<_CharT> __cd{}; + auto __parts = _M_f._M_spec._M_needed; + __parts = __cd._M_fill_year_month(__t, __parts); + if (_M_f._M_spec._M_needs(_Day|_WeekdayIndex)) + __parts = __cd._M_fill_day(__t.day(), __parts); + if (__parts == 0) + return _M_f._M_format(__cd, __fc); + + __cd._M_fill_ldays(chrono::local_days(__t), __parts); + return _M_f._M_format(__cd, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = [] + { + using __format::_ChronoFormats; + using enum __format::_ChronoParts; + + __format::_ChronoSpec<_CharT> __res{}; + __res._M_debug = true; + __res._M_localized = true; + __res._M_locale_specific = true; + __res._M_needed = _Year|_Month; + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_yml(); + return __res; + }(); + + __format::__formatter_chrono<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::year_month_day_last> = true; +#endif + template<__format::__char _CharT> struct formatter<chrono::year_month_weekday, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_Date); } + { + using enum __format::_ChronoParts; + return _M_f._M_parse(__pc, _Date, __defSpec); + } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::year_month_weekday& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + __format::_ChronoData<_CharT> __cd{}; + auto __parts = _M_f._M_spec._M_needed; + __parts = __cd._M_fill_year_month(__t, __parts); + __parts = __cd._M_fill_weekday(__t.weekday_indexed(), __parts); + if (__t.index() == 0) [[unlikely]] + // n.b. day cannot be negative, so any 0th weekday uses + // value-initialized (0) day of month + __parts -= __format::_ChronoParts::_Day; + if (__parts == 0) + return _M_f._M_format(__cd, __fc); + + chrono::local_days __ld(__t); + __parts = __cd._M_fill_ldays(__ld, __parts); + if (__parts == 0) + return _M_f._M_format(__cd, __fc); + + auto __dom = __ld - chrono::local_days(__t.year()/__t.month()/0); + // n.b. weekday index is supplied by input, do not override it + __cd._M_day = chrono::day(__dom.count()); + return _M_f._M_format(__cd, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = [] + { + using __format::_ChronoFormats; + using enum __format::_ChronoParts; + + __format::_ChronoSpec<_CharT> __res{}; + __res._M_debug = true; + __res._M_localized = true; + __res._M_locale_specific = true; + __res._M_needed = _Year|_Month|_IndexedWeekday; + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_ymwi(); + return __res; + }(); + + __format::__formatter_chrono<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::year_month_weekday> = true; +#endif + template<__format::__char _CharT> struct formatter<chrono::year_month_weekday_last, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_Date); } + { + using enum __format::_ChronoParts; + return _M_f._M_parse(__pc, _Date, __defSpec); + } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::year_month_weekday_last& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + __format::_ChronoData<_CharT> __cd{}; + auto __parts = _M_f._M_spec._M_needed; + __parts = __cd._M_fill_year_month(__t, __parts); + __cd._M_weekday = __t.weekday_last().weekday(); + __parts -= __format::_ChronoParts::_Weekday; + if (__parts == 0) + return _M_f._M_format(__cd, __fc); + + chrono::local_days __ld(__t); + __parts = __cd._M_fill_ldays(__ld, __parts); + if (__parts == 0) + return _M_f._M_format(__cd, __fc); + + auto __dom = __ld - chrono::local_days(__t.year()/__t.month()/0); + __cd._M_fill_day(chrono::day(__dom.count()), __parts); + return _M_f._M_format(__cd, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = [] + { + using __format::_ChronoFormats; + using enum __format::_ChronoParts; + + __format::_ChronoSpec<_CharT> __res{}; + __res._M_debug = true; + __res._M_localized = true; + __res._M_locale_specific = true; + __res._M_needed = _Year|_Month|_Weekday; + __res._M_chrono_specs = _ChronoFormats<_CharT>::_S_ymwl(); + return __res; + }(); + + __format::__formatter_chrono<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::year_month_weekday_last> = true; +#endif + template<typename _Rep, typename _Period, __format::__char _CharT> struct formatter<chrono::hh_mm_ss<chrono::duration<_Rep, _Period>>, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_TimeOfDay); } + { + using enum __format::_ChronoParts; + return _M_f.template _M_parse<_Precision>(__pc, _Time, __defSpec); + } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::hh_mm_ss<chrono::duration<_Rep, _Period>>& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + using enum __format::_ChronoParts; + + __format::_ChronoData<_CharT> __cd; + __cd._M_is_neg = __t.is_negative(); + __cd._M_hours = __t.hours(); + __cd._M_minutes = __t.minutes(); + __cd._M_seconds = __t.seconds(); + + _Precision __d(0); + // n.b. computing total duration or total seconds may overflow, + // do not compute them if not requested. + if (_M_f._M_spec._M_needs(_EpochUnits)) + __d = __t.to_duration(); + if (_M_f._M_spec._M_needs(_TotalSeconds)) + __cd._M_eseconds + = __cd._M_hours + __cd._M_minutes + __cd._M_seconds; + return _M_f._M_format_units(__cd, __d, __t.subseconds(), __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + using _Precision + = typename chrono::hh_mm_ss<chrono::duration<_Rep, _Period>>::precision; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = + __format::__formatter_duration<_CharT>:: + template _S_spec_for<_Precision>(__format::_ChronoParts::_Time); + + __format::__formatter_duration<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4400. enable_nonlocking_formatter_optimization for durations with custom rep + template<typename _Duration> + constexpr bool + enable_nonlocking_formatter_optimization<chrono::hh_mm_ss<_Duration>> + = enable_nonlocking_formatter_optimization<_Duration>; +#endif + #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI template<__format::__char _CharT> struct formatter<chrono::sys_info, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_ChronoParts{}); } + { return _M_f.parse(__pc); } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::sys_info& __i, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__i, __fc); } + { return _M_f.format(__i, __fc); } private: - __format::__formatter_chrono<_CharT> _M_f; + __format::__formatter_chrono_info<_CharT> _M_f; }; +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::sys_info> = true; +#endif + template<__format::__char _CharT> struct formatter<chrono::local_info, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_ChronoParts{}); } + { return _M_f.parse(__pc); } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::local_info& __i, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__i, __fc); } + { return _M_f.format(__i, __fc); } private: - __format::__formatter_chrono<_CharT> _M_f; + __format::__formatter_chrono_info<_CharT> _M_f; }; + +#if __glibcxx_print >= 202406L + template<> + inline constexpr bool + enable_nonlocking_formatter_optimization<chrono::local_info> = true; +#endif #endif template<typename _Duration, __format::__char _CharT> @@ -2075,185 +3052,351 @@ namespace __format constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) { - auto __next = _M_f._M_parse(__pc, __format::_ZonedDateTime); - if constexpr (!__stream_insertable) + using enum __format::_ChronoParts; + auto __res + = _M_f.template _M_parse<_Duration>(__pc, _ZonedDateTime, __defSpec); + if constexpr (__defSpec._M_chrono_specs.empty()) if (_M_f._M_spec._M_chrono_specs.empty()) __format::__invalid_chrono_spec(); // chrono-specs can't be empty - return __next; + return __res; } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const chrono::sys_time<_Duration>& __t, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + __format::_ChronoData<_CharT> __cd{}; + __cd._M_fill_utc_zone(); + + _Duration __ed = __t.time_since_epoch(); + __cd._M_eseconds = chrono::floor<chrono::seconds>(__ed); + __cd._M_lseconds = chrono::local_seconds(__cd._M_eseconds); + return _M_f._M_format_time_point(__cd, __ed, __fc); + } private: - static constexpr bool __stream_insertable - = requires (basic_ostream<_CharT>& __os, - chrono::sys_time<_Duration> __t) { __os << __t; }; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = + __format::__formatter_duration<_CharT>::template _S_spec_for_tp<_Duration>(); - __format::__formatter_chrono<_CharT> _M_f; + __format::__formatter_duration<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4400. enable_nonlocking_formatter_optimization for durations with custom rep + template<typename _Duration> + constexpr bool + enable_nonlocking_formatter_optimization<chrono::sys_time<_Duration>> + = enable_nonlocking_formatter_optimization<_Duration>; +#endif + template<typename _Duration, __format::__char _CharT> struct formatter<chrono::utc_time<_Duration>, _CharT> - : __format::__formatter_chrono<_CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } + { + using enum __format::_ChronoParts; + return _M_f.template _M_parse<_Duration>(__pc, _ZonedDateTime, __defSpec); + } template<typename _Out> - typename basic_format_context<_Out, _CharT>::iterator - format(const chrono::utc_time<_Duration>& __t, + typename basic_format_context<_Out, _CharT>::iterator + format(const chrono::utc_time<_Duration>& __t, basic_format_context<_Out, _CharT>& __fc) const { + using __format::_ChronoParts; + using namespace chrono; + __format::_ChronoData<_CharT> __cd{}; + __cd._M_fill_utc_zone(); + + _Duration __ed = __t.time_since_epoch(); + __cd._M_eseconds = chrono::floor<seconds>(__ed); // Adjust by removing leap seconds to get equivalent sys_time. // We can't just use clock_cast because we want to know if the time // falls within a leap second insertion, and format seconds as "60". - using chrono::__detail::__utc_leap_second; - using chrono::seconds; - using chrono::sys_time; - using _CDur = common_type_t<_Duration, seconds>; const auto __li = chrono::get_leap_second_info(__t); - sys_time<_CDur> __s{__t.time_since_epoch() - __li.elapsed}; - if (!__li.is_leap_second) [[likely]] - return _M_f._M_format(__s, __fc); - else - return _M_f._M_format(__utc_leap_second(__s), __fc); + __cd._M_lseconds = local_seconds(__cd._M_eseconds - __li.elapsed); + auto __parts = _M_f._M_spec._M_needed - _ChronoParts::_TotalSeconds; + if ((__parts & _ChronoParts::_DateTime) != 0) + { + __cd._M_fill_date_time(__cd._M_lseconds, __parts); + __cd._M_seconds += seconds(__li.is_leap_second); + } + return _M_f._M_format_units(__cd, __ed, __ed - __cd._M_eseconds, __fc); } private: - friend formatter<chrono::__detail::__utc_leap_second<_Duration>, _CharT>; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = + __format::__formatter_duration<_CharT>:: + template _S_spec_for<_Duration>(__format::_ChronoParts::_DateTime); - __format::__formatter_chrono<_CharT> _M_f; + __format::__formatter_duration<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4400. enable_nonlocking_formatter_optimization for durations with custom rep + template<typename _Duration> + constexpr bool + enable_nonlocking_formatter_optimization<chrono::utc_time<_Duration>> + = enable_nonlocking_formatter_optimization<_Duration>; +#endif + template<typename _Duration, __format::__char _CharT> struct formatter<chrono::tai_time<_Duration>, _CharT> - : __format::__formatter_chrono<_CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } + { + using enum __format::_ChronoParts; + return _M_f.template _M_parse<_Duration>(__pc, _ZonedDateTime, __defSpec); + } template<typename _Out> - typename basic_format_context<_Out, _CharT>::iterator - format(const chrono::tai_time<_Duration>& __t, + typename basic_format_context<_Out, _CharT>::iterator + format(const chrono::tai_time<_Duration>& __t, basic_format_context<_Out, _CharT>& __fc) const { - // Convert to __local_time_fmt with abbrev "TAI" and offset 0s. - // We use __local_time_fmt and not sys_time (as the standard implies) - // because %Z for sys_time would print "UTC" and we want "TAI" here. + using namespace chrono; + __format::_ChronoData<_CharT> __cd{}; + __cd._M_fill_zone("TAI", L"TAI"); + _Duration __ed = __t.time_since_epoch(); + __cd._M_eseconds = chrono::floor<seconds>(__ed); // Offset is 1970y/January/1 - 1958y/January/1 constexpr chrono::days __tai_offset = chrono::days(4383); - using _CDur = common_type_t<_Duration, chrono::days>; - chrono::local_time<_CDur> __lt(__t.time_since_epoch() - __tai_offset); - const string __abbrev("TAI", 3); - const chrono::seconds __off = 0s; - const auto __lf = chrono::local_time_format(__lt, &__abbrev, &__off); - return _M_f._M_format(__lf, __fc); + __cd._M_lseconds = local_seconds(__cd._M_eseconds - __tai_offset); + return _M_f._M_format_time_point(__cd, __ed, __fc); } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = + __format::__formatter_duration<_CharT>:: + template _S_spec_for<_Duration>(__format::_ChronoParts::_DateTime); + + __format::__formatter_duration<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4400. enable_nonlocking_formatter_optimization for durations with custom rep + template<typename _Duration> + constexpr bool + enable_nonlocking_formatter_optimization<chrono::tai_time<_Duration>> + = enable_nonlocking_formatter_optimization<_Duration>; +#endif + template<typename _Duration, __format::__char _CharT> struct formatter<chrono::gps_time<_Duration>, _CharT> - : __format::__formatter_chrono<_CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } + { + using enum __format::_ChronoParts; + return _M_f.template _M_parse<_Duration>(__pc, _ZonedDateTime, __defSpec); + } template<typename _Out> - typename basic_format_context<_Out, _CharT>::iterator - format(const chrono::gps_time<_Duration>& __t, + typename basic_format_context<_Out, _CharT>::iterator + format(const chrono::gps_time<_Duration>& __t, basic_format_context<_Out, _CharT>& __fc) const { - // Convert to __local_time_fmt with abbrev "GPS" and offset 0s. - // We use __local_time_fmt and not sys_time (as the standard implies) - // because %Z for sys_time would print "UTC" and we want "GPS" here. + using namespace chrono; + __format::_ChronoData<_CharT> __cd{}; + __cd._M_fill_zone("GPS", L"GPS"); + _Duration __ed = __t.time_since_epoch(); + __cd._M_eseconds = chrono::floor<seconds>(__ed); // Offset is 1980y/January/Sunday[1] - 1970y/January/1 constexpr chrono::days __gps_offset = chrono::days(3657); - using _CDur = common_type_t<_Duration, chrono::days>; - chrono::local_time<_CDur> __lt(__t.time_since_epoch() + __gps_offset); - const string __abbrev("GPS", 3); - const chrono::seconds __off = 0s; - const auto __lf = chrono::local_time_format(__lt, &__abbrev, &__off); - return _M_f._M_format(__lf, __fc); + __cd._M_lseconds = local_seconds(__cd._M_eseconds + __gps_offset); + return _M_f._M_format_time_point(__cd, __ed, __fc); } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = + __format::__formatter_duration<_CharT>:: + template _S_spec_for<_Duration>(__format::_ChronoParts::_DateTime); + + __format::__formatter_duration<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4400. enable_nonlocking_formatter_optimization for durations with custom rep + template<typename _Duration> + constexpr bool + enable_nonlocking_formatter_optimization<chrono::gps_time<_Duration>> + = enable_nonlocking_formatter_optimization<_Duration>; +#endif + template<typename _Duration, __format::__char _CharT> struct formatter<chrono::file_time<_Duration>, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } + { + using enum __format::_ChronoParts; + return _M_f.template _M_parse<_Duration>(__pc, _ZonedDateTime, __defSpec); + } template<typename _Out> - typename basic_format_context<_Out, _CharT>::iterator - format(const chrono::file_time<_Duration>& __t, + typename basic_format_context<_Out, _CharT>::iterator + format(const chrono::file_time<_Duration>& __t, basic_format_context<_Out, _CharT>& __fc) const { using namespace chrono; - return _M_f._M_format(chrono::clock_cast<system_clock>(__t), __fc); + __format::_ChronoData<_CharT> __cd{}; + __cd._M_fill_utc_zone(); + + _Duration __ed = __t.time_since_epoch(); + __cd._M_eseconds = chrono::floor<seconds>(__ed); + auto __st = chrono::clock_cast<system_clock>(__t); + __cd._M_lseconds + = local_seconds(chrono::floor<seconds>(__st.time_since_epoch())); + return _M_f._M_format_time_point(__cd, __ed, __fc); } private: - __format::__formatter_chrono<_CharT> _M_f; - }; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = + __format::__formatter_duration<_CharT>:: + template _S_spec_for<_Duration>(__format::_ChronoParts::_DateTime); + + __format::__formatter_duration<_CharT> _M_f{__defSpec}; + }; + +#if __glibcxx_print >= 202406L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4400. enable_nonlocking_formatter_optimization for durations with custom rep + template<typename _Duration> + constexpr bool + enable_nonlocking_formatter_optimization<chrono::file_time<_Duration>> + = enable_nonlocking_formatter_optimization<_Duration>; +#endif template<typename _Duration, __format::__char _CharT> struct formatter<chrono::local_time<_Duration>, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_DateTime); } + { + using enum __format::_ChronoParts; + auto __res + = _M_f.template _M_parse<_Duration>(__pc, _DateTime, __defSpec); + if constexpr (__defSpec._M_chrono_specs.empty()) + if (_M_f._M_spec._M_chrono_specs.empty()) + __format::__invalid_chrono_spec(); // chrono-specs can't be empty + return __res; + } template<typename _Out> - typename basic_format_context<_Out, _CharT>::iterator - format(const chrono::local_time<_Duration>& __t, + typename basic_format_context<_Out, _CharT>::iterator + format(const chrono::local_time<_Duration>& __lt, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc); } + { + __format::_ChronoData<_CharT> __cd{}; + _Duration __ed = __lt.time_since_epoch(); + __cd._M_lseconds = chrono::floor<chrono::seconds>(__lt); + __cd._M_eseconds = __cd._M_lseconds.time_since_epoch(); + return _M_f._M_format_time_point(__cd, __ed, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = + __format::__formatter_duration<_CharT>::template _S_spec_for_tp<_Duration>(); + + __format::__formatter_duration<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4400. enable_nonlocking_formatter_optimization for durations with custom rep + template<typename _Duration> + constexpr bool + enable_nonlocking_formatter_optimization<chrono::local_time<_Duration>> + = enable_nonlocking_formatter_optimization<_Duration>; +#endif + template<typename _Duration, __format::__char _CharT> struct formatter<chrono::__detail::__local_time_fmt<_Duration>, _CharT> { constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } + { + using enum __format::_ChronoParts; + return _M_f.template _M_parse<_Duration>(__pc, _ZonedDateTime, __defSpec); + } template<typename _Out> - typename basic_format_context<_Out, _CharT>::iterator - format(const chrono::__detail::__local_time_fmt<_Duration>& __t, + typename basic_format_context<_Out, _CharT>::iterator + format(const chrono::__detail::__local_time_fmt<_Duration>& __zt, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f._M_format(__t, __fc, /* use %Z for {} */ true); } + { + using enum __format::_ChronoParts; + __format::_ChronoData<_CharT> __cd{}; + + if (_M_f._M_spec._M_needs(_ZoneOffset)) + { + if (!__zt._M_offset_sec) + std::__throw_format_error("format error: no timezone available for %z"); + __cd._M_zone_offset = *__zt._M_offset_sec; + } + + basic_string<_CharT> __zone_store; + if (_M_f._M_spec._M_needs(_ZoneAbbrev)) + { + if (!__zt._M_abbrev) + std::__throw_format_error("format error: no timezone available for %Z"); + + __cd._M_zone_cstr = __zt._M_abbrev->data(); + if constexpr (is_same_v<_CharT, char>) + __cd._M_zone_abbrev = *__zt._M_abbrev; + else + { + // TODO: use resize_for_override + __zone_store.resize(__zt._M_abbrev->size()); + auto& __ct = use_facet<ctype<_CharT>>(_M_f._M_locale(__fc)); + __ct.widen(__zt._M_abbrev->data(), + __zt._M_abbrev->data() + __zt._M_abbrev->size(), + __zone_store.data()); + __cd._M_zone_abbrev = __zone_store; + } + } + + _Duration __ed = __zt._M_time.time_since_epoch(); + __cd._M_lseconds = chrono::floor<chrono::seconds>(__zt._M_time); + __cd._M_eseconds = __cd._M_lseconds.time_since_epoch(); + return _M_f._M_format_time_point(__cd, __ed, __fc); + } private: - __format::__formatter_chrono<_CharT> _M_f; + static constexpr __format::_ChronoSpec<_CharT> __defSpec = + __format::__formatter_duration<_CharT>:: + template _S_spec_for<_Duration>(__format::_ChronoParts::_ZonedDateTime); + + __format::__formatter_duration<_CharT> _M_f{__defSpec}; }; +#if __glibcxx_print >= 202406L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4400. enable_nonlocking_formatter_optimization for durations with custom rep + template<typename _Duration> + constexpr bool + enable_nonlocking_formatter_optimization< + chrono::__detail::__local_time_fmt<_Duration>> + = enable_nonlocking_formatter_optimization<_Duration>; +#endif + #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI template<typename _Duration, typename _TimeZonePtr, __format::__char _CharT> struct formatter<chrono::zoned_time<_Duration, _TimeZonePtr>, _CharT> : formatter<chrono::__detail::__local_time_fmt_for<_Duration>, _CharT> { template<typename _Out> - typename basic_format_context<_Out, _CharT>::iterator - format(const chrono::zoned_time<_Duration, _TimeZonePtr>& __tp, + typename basic_format_context<_Out, _CharT>::iterator + format(const chrono::zoned_time<_Duration, _TimeZonePtr>& __tp, basic_format_context<_Out, _CharT>& __fc) const { using _Ltf = chrono::__detail::__local_time_fmt_for<_Duration>; @@ -2265,19 +3408,17 @@ namespace __format return _Base::format(__lf, __fc); } }; -#endif - // Partial specialization needed for %c formatting of __utc_leap_second. - template<typename _Duration, __format::__char _CharT> - struct formatter<chrono::__detail::__utc_leap_second<_Duration>, _CharT> - : formatter<chrono::utc_time<_Duration>, _CharT> - { - template<typename _Out> - typename basic_format_context<_Out, _CharT>::iterator - format(const chrono::__detail::__utc_leap_second<_Duration>& __t, - basic_format_context<_Out, _CharT>& __fc) const - { return this->_M_f._M_format(__t, __fc); } - }; +#if __glibcxx_print >= 202406L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4400. enable_nonlocking_formatter_optimization for durations with custom rep + template<typename _Duration> + constexpr bool + enable_nonlocking_formatter_optimization< + chrono::zoned_time<_Duration, const chrono::time_zone*>> + = enable_nonlocking_formatter_optimization<_Duration>; +#endif +#endif namespace chrono { @@ -2859,10 +4000,7 @@ namespace __detail basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const sys_info& __i) { - __os << '[' << __i.begin << ',' << __i.end - << ',' << hh_mm_ss(__i.offset) << ',' << __i.save - << ',' << __i.abbrev << ']'; - return __os; + return __os << std::format(__os.getloc(), _GLIBCXX_WIDEN("{}"), __i); } /// Writes a local_info object to an ostream in an unspecified format. @@ -2870,19 +4008,19 @@ namespace __detail basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const local_info& __li) { - __os << '['; + __os << __format::_Separators<_CharT>::_S_squares()[0]; if (__li.result == local_info::unique) __os << __li.first; else { if (__li.result == local_info::nonexistent) - __os << "nonexistent"; + __os << _GLIBCXX_WIDEN("nonexistent"); else - __os << "ambiguous"; - __os << " local time between " << __li.first; - __os << " and " << __li.second; + __os << _GLIBCXX_WIDEN("ambiguous"); + __os << _GLIBCXX_WIDEN(" local time between ") << __li.first; + __os << _GLIBCXX_WIDEN(" and ") << __li.second; } - __os << ']'; + __os << __format::_Separators<_CharT>::_S_squares()[1]; return __os; } @@ -3039,8 +4177,7 @@ namespace __detail if (!__offset) __offset = &__off; using __format::_ChronoParts; - auto __need = _ChronoParts::_Year | _ChronoParts::_Month - | _ChronoParts::_Day | _ChronoParts::_TimeOfDay; + auto __need = _ChronoParts::_YearMonthDay | _ChronoParts::_TimeOfDay; __detail::_Parser_t<_Duration> __p(__need); if (__p(__is, __fmt, __abbrev, __offset)) { @@ -3084,6 +4221,9 @@ namespace __detail inline basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __os, const local_time<_Duration>& __lt) + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4257. Stream insertion for chrono::local_time should be constrained + requires requires(const sys_time<_Duration>& __st) { __os << __st; } { __os << sys_time<_Duration>{__lt.time_since_epoch()}; return __os; @@ -3098,8 +4238,7 @@ namespace __detail minutes* __offset = nullptr) { using __format::_ChronoParts; - auto __need = _ChronoParts::_Year | _ChronoParts::_Month - | _ChronoParts::_Day | _ChronoParts::_TimeOfDay; + auto __need = _ChronoParts::_YearMonthDay | _ChronoParts::_TimeOfDay; __detail::_Parser_t<_Duration> __p(__need); if (__p(__is, __fmt, __abbrev, __offset)) { @@ -3352,8 +4491,8 @@ namespace __detail minutes __tz_offset = __bad_min; basic_string<_CharT, _Traits> __tz_abbr; - if ((_M_need & _ChronoParts::_TimeOfDay) - && (_M_need & _ChronoParts::_Year)) + if ((_M_need & _ChronoParts::_TimeOfDay) != 0 + && (_M_need & _ChronoParts::_Year) != 0) { // For time_points assume "00:00:00" is implicitly present, // so we don't fail to parse if it's not (PR libstdc++/114240). @@ -3626,7 +4765,7 @@ namespace __detail } else { - if (_M_need & _ChronoParts::_TimeOfDay) + if ((_M_need & _ChronoParts::_TimeOfDay) != 0) __err |= ios_base::failbit; break; } @@ -3694,7 +4833,7 @@ namespace __detail __min = minutes(__val); else { - if (_M_need & _ChronoParts::_TimeOfDay) + if ((_M_need & _ChronoParts::_TimeOfDay) != 0) __err |= ios_base::failbit; break; } @@ -3784,7 +4923,7 @@ namespace __detail auto __val = __read_unsigned(2); if (__val == -1 || __val > 23) [[unlikely]] { - if (_M_need & _ChronoParts::_TimeOfDay) + if ((_M_need & _ChronoParts::_TimeOfDay) != 0) __err |= ios_base::failbit; break; } @@ -3795,7 +4934,7 @@ namespace __detail __val = __read_unsigned(2); if (__val == -1 || __val > 60) [[unlikely]] { - if (_M_need & _ChronoParts::_TimeOfDay) + if ((_M_need & _ChronoParts::_TimeOfDay) != 0) __err |= ios_base::failbit; break; } @@ -3830,7 +4969,7 @@ namespace __detail __s = seconds(__val); else { - if (_M_need & _ChronoParts::_TimeOfDay) + if ((_M_need & _ChronoParts::_TimeOfDay) != 0) __err |= ios_base::failbit; break; } @@ -4304,23 +5443,23 @@ namespace __detail // Whether the caller wants _M_wd. // The _Weekday bit is only set for chrono::weekday. - const bool __need_wday = _M_need & _ChronoParts::_Weekday; + const bool __need_wday = (_M_need & _ChronoParts::_Weekday) != 0; // Whether the caller wants _M_sys_days and _M_time. // Only true for durations and time_points. - const bool __need_time = _M_need & _ChronoParts::_TimeOfDay; + const bool __need_time = (_M_need & _ChronoParts::_TimeOfDay) != 0; if (__need_wday && __wday != __bad_wday) _M_wd = __wday; // Caller only wants a weekday and we have one. - else if (_M_need & _ChronoParts::_Date) // subsumes __need_wday + else if ((_M_need & _ChronoParts::_Date) != 0) // subsumes __need_wday { // Whether the caller wants _M_ymd. // True for chrono::year etc., false for time_points. const bool __need_ymd = !__need_wday && !__need_time; - if ((_M_need & _ChronoParts::_Year && __y == __bad_y) - || (_M_need & _ChronoParts::_Month && __m == __bad_mon) - || (_M_need & _ChronoParts::_Day && __d == __bad_day)) + if (((_M_need & _ChronoParts::_Year) != 0 && __y == __bad_y) + || ((_M_need & _ChronoParts::_Month) != 0 && __m == __bad_mon) + || ((_M_need & _ChronoParts::_Day) != 0 && __d == __bad_day)) { // Missing at least one of y/m/d so calculate sys_days // from the other data we have available. @@ -4397,7 +5536,7 @@ namespace __detail // but check that their values are in range. // Make unwanted fields valid so that _M_ymd.ok() is true. - if (_M_need & _ChronoParts::_Year) + if ((_M_need & _ChronoParts::_Year) != 0) { if (!__y.ok()) [[unlikely]] __err |= ios_base::failbit; @@ -4405,7 +5544,7 @@ namespace __detail else if (__y == __bad_y) __y = 1972y; // Leap year so that Feb 29 is valid. - if (_M_need & _ChronoParts::_Month) + if ((_M_need & _ChronoParts::_Month) != 0) { if (!__m.ok()) [[unlikely]] __err |= ios_base::failbit; @@ -4413,7 +5552,7 @@ namespace __detail else if (__m == __bad_mon) __m = January; - if (_M_need & _ChronoParts::_Day) + if ((_M_need & _ChronoParts::_Day) != 0) { if (__d < day(1) || __d > (__y/__m/last).day()) __err |= ios_base::failbit; diff --git a/libstdc++-v3/include/bits/cow_string.h b/libstdc++-v3/include/bits/cow_string.h index f9df2be..e59897e 100644 --- a/libstdc++-v3/include/bits/cow_string.h +++ b/libstdc++-v3/include/bits/cow_string.h @@ -2919,6 +2919,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return basic_string(*this, _M_check(__pos, "basic_string::substr"), __n); } +#ifdef __glibcxx_string_subview // >= C++26 + /** + * @brief Get a subview. + * @param __pos Index of first character (default 0). + * @param __n Number of characters in subview (default remainder). + * @return The subview. + * @throw std::out_of_range If __pos > size(). + * + * Construct and return a subview using the `__n` characters starting at + * `__pos`. If the string is too short, use the remainder of the + * characters. If `__pos` is beyond the end of the string, out_of_range + * is thrown. + */ + [[nodiscard]] + constexpr basic_string_view<_CharT, _Traits> + subview(size_type __pos = 0, size_type __n = npos) const + { return __sv_type(*this).subview(__pos, __n); } +#endif + /** * @brief Compare to a string. * @param __str String to compare against. diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h index b1a6206..38cea4c 100644 --- a/libstdc++-v3/include/bits/cpp_type_traits.h +++ b/libstdc++-v3/include/bits/cpp_type_traits.h @@ -273,6 +273,12 @@ __INT_N(__GLIBCXX_TYPE_INT_N_2) __INT_N(__GLIBCXX_TYPE_INT_N_3) #endif +#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ +// In strict modes __GLIBCXX_TYPE_INT_N_0 is not defined for __int128, +// but we want to always treat signed/unsigned __int128 as integral types. +__INT_N(__int128) +#endif + #undef __INT_N // @@ -307,6 +313,15 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3) typedef __true_type __type; }; +#ifdef _GLIBCXX_USE_FLOAT128 + template<> + struct __is_floating<__float128> + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + #ifdef __STDCPP_FLOAT16_T__ template<> struct __is_floating<_Float16> @@ -545,17 +560,6 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3) { enum { __width = __GLIBCXX_BITSIZE_INT_N_3 }; }; #endif -#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ - // In strict modes __is_integer<__int128> is false, - // but we want to allow memcpy between signed/unsigned __int128. - __extension__ - template<> - struct __memcpyable_integer<__int128> { enum { __width = 128 }; }; - __extension__ - template<> - struct __memcpyable_integer<unsigned __int128> { enum { __width = 128 }; }; -#endif - #if _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 && _GLIBCXX_LDOUBLE_IS_IEEE_BINARY64 template<> struct __memcpyable<double*, long double*> { enum { __value = true }; }; diff --git a/libstdc++-v3/include/bits/cpyfunc_impl.h b/libstdc++-v3/include/bits/cpyfunc_impl.h new file mode 100644 index 0000000..f1918dd --- /dev/null +++ b/libstdc++-v3/include/bits/cpyfunc_impl.h @@ -0,0 +1,273 @@ +// Implementation of std::copyable_function -*- C++ -*- + +// Copyright The GNU Toolchain Authors. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file include/bits/cpyfunc_impl.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _GLIBCXX_MOF_CV +# define _GLIBCXX_MOF_CV +#endif + +#ifdef _GLIBCXX_MOF_REF +# define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF +#else +# define _GLIBCXX_MOF_REF +# define _GLIBCXX_MOF_INV_QUALS _GLIBCXX_MOF_CV & +#endif + +#define _GLIBCXX_MOF_CV_REF _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief Polymorphic copyable function wrapper. + * @ingroup functors + * @since C++26 + * @headerfile functional + * + * The `std::copyable_function` class template is a call wrapper similar + * to `std::function`, but it does not provide information about it's + * target, and preserves constness. + * + * It also supports const-qualification, ref-qualification, and + * no-throw guarantees. The qualifications and exception-specification + * of the `copyable_function::operator()` member function are respected + * when invoking the target function. + */ + template<typename _Res, typename... _ArgTypes, bool _Noex> + class copyable_function<_Res(_ArgTypes...) _GLIBCXX_MOF_CV + _GLIBCXX_MOF_REF noexcept(_Noex)> + : __polyfunc::_Cpy_base + { + static_assert( + (std::__is_complete_or_unbounded(__type_identity<_ArgTypes>()) && ...), + "each parameter type must be a complete class"); + + using _Base = __polyfunc::_Cpy_base; + using _Invoker = __polyfunc::_Invoker<_Noex, _Res, _ArgTypes...>; + using _Signature = _Invoker::_Signature; + + template<typename _Tp> + using __callable + = __conditional_t<_Noex, + is_nothrow_invocable_r<_Res, _Tp, _ArgTypes...>, + is_invocable_r<_Res, _Tp, _ArgTypes...>>; + + // [func.wrap.copy.con]/1 is-callable-from<VT> + template<typename _Vt> + static constexpr bool __is_callable_from + = __and_v<__callable<_Vt _GLIBCXX_MOF_CV_REF>, + __callable<_Vt _GLIBCXX_MOF_INV_QUALS>>; + + public: + using result_type = _Res; + + /// Creates an empty object. + copyable_function() noexcept { } + + /// Creates an empty object. + copyable_function(nullptr_t) noexcept { } + + /// Moves the target object, leaving the source empty. + copyable_function(copyable_function&& __x) noexcept + : _Base(static_cast<_Base&&>(__x)), + _M_invoke(std::__exchange(__x._M_invoke, nullptr)) + { } + + /// Copies the target object. + copyable_function(copyable_function const& __x) + : _Base(static_cast<const _Base&>(__x)), + _M_invoke(__x._M_invoke) + { } + + /// Stores a target object initialized from the argument. + template<typename _Fn, typename _Vt = decay_t<_Fn>> + requires (!is_same_v<_Vt, copyable_function>) + && (!__is_in_place_type_v<_Vt>) && __is_callable_from<_Vt> + copyable_function(_Fn&& __f) noexcept(_S_nothrow_init<_Vt, _Fn>()) + { + static_assert(is_copy_constructible_v<_Vt>); + if constexpr (is_function_v<remove_pointer_t<_Vt>> + || is_member_pointer_v<_Vt> + || __is_polymorphic_function_v<_Vt>) + { + if (__f == nullptr) + return; + } + + if constexpr (!__is_polymorphic_function_v<_Vt> + || !__polyfunc::__is_invoker_convertible<_Vt, copyable_function>()) + { + _M_init<_Vt>(std::forward<_Fn>(__f)); + _M_invoke = _Invoker::template _S_storage<_Vt _GLIBCXX_MOF_INV_QUALS>(); + } + else if constexpr (is_lvalue_reference_v<_Fn>) + { + _M_copy(__polyfunc::__base_of(__f)); + _M_invoke = __polyfunc::__invoker_of(__f); + } + else + { + _M_move(__polyfunc::__base_of(__f)); + _M_invoke = std::__exchange(__polyfunc::__invoker_of(__f), nullptr); + } + } + + /// Stores a target object initialized from the arguments. + template<typename _Tp, typename... _Args> + requires is_constructible_v<_Tp, _Args...> + && __is_callable_from<_Tp> + explicit + copyable_function(in_place_type_t<_Tp>, _Args&&... __args) + noexcept(_S_nothrow_init<_Tp, _Args...>()) + : _M_invoke(_Invoker::template _S_storage<_Tp _GLIBCXX_MOF_INV_QUALS>()) + { + static_assert(is_same_v<decay_t<_Tp>, _Tp>); + static_assert(is_copy_constructible_v<_Tp>); + _M_init<_Tp>(std::forward<_Args>(__args)...); + } + + /// Stores a target object initialized from the arguments. + template<typename _Tp, typename _Up, typename... _Args> + requires is_constructible_v<_Tp, initializer_list<_Up>&, _Args...> + && __is_callable_from<_Tp> + explicit + copyable_function(in_place_type_t<_Tp>, initializer_list<_Up> __il, + _Args&&... __args) + noexcept(_S_nothrow_init<_Tp, initializer_list<_Up>&, _Args...>()) + : _M_invoke(_Invoker::template _S_storage<_Tp _GLIBCXX_MOF_INV_QUALS>()) + { + static_assert(is_same_v<decay_t<_Tp>, _Tp>); + static_assert(is_copy_constructible_v<_Tp>); + _M_init<_Tp>(__il, std::forward<_Args>(__args)...); + } + + /// Stores a new target object, leaving `x` empty. + copyable_function& + operator=(copyable_function&& __x) noexcept + { + // Standard requires support of self assigment, by specifying it as + // copy and swap. + if (this != std::addressof(__x)) [[likely]] + { + _Base::operator=(static_cast<_Base&&>(__x)); + _M_invoke = std::__exchange(__x._M_invoke, nullptr); + } + return *this; + } + + /// Stores a copy of the source target object + copyable_function& + operator=(const copyable_function& __x) + { + copyable_function(__x).swap(*this); + return *this; + } + + /// Destroys the target object (if any). + copyable_function& + operator=(nullptr_t) noexcept + { + _M_reset(); + _M_invoke = nullptr; + return *this; + } + + /// Stores a new target object, initialized from the argument. + template<typename _Fn> + requires is_constructible_v<copyable_function, _Fn> + copyable_function& + operator=(_Fn&& __f) + noexcept(is_nothrow_constructible_v<copyable_function, _Fn>) + { + copyable_function(std::forward<_Fn>(__f)).swap(*this); + return *this; + } + + ~copyable_function() = default; + + /// True if a target object is present, false otherwise. + explicit operator bool() const noexcept + { return _M_invoke != nullptr; } + + /** Invoke the target object. + * + * The target object will be invoked using the supplied arguments, + * and as an lvalue or rvalue, and as const or non-const, as dictated + * by the template arguments of the `copyable_function` specialization. + * + * @pre Must not be empty. + */ + _Res + operator()(_ArgTypes... __args) _GLIBCXX_MOF_CV_REF noexcept(_Noex) + { + __glibcxx_assert(*this != nullptr); + return _M_invoke(this->_M_storage, std::forward<_ArgTypes>(__args)...); + } + + /// Exchange the target objects (if any). + void + swap(copyable_function& __x) noexcept + { + _Base::swap(__x); + std::swap(_M_invoke, __x._M_invoke); + } + + /// Exchange the target objects (if any). + friend void + swap(copyable_function& __x, copyable_function& __y) noexcept + { __x.swap(__y); } + + /// Check for emptiness by comparing with `nullptr`. + friend bool + operator==(const copyable_function& __x, nullptr_t) noexcept + { return __x._M_invoke == nullptr; } + + private: + typename _Invoker::__storage_func_t _M_invoke = nullptr; + + template<typename _Func> + friend auto& + __polyfunc::__invoker_of(_Func&) noexcept; + + template<typename _Func> + friend auto& + __polyfunc::__base_of(_Func&) noexcept; + + template<typename _Dst, typename _Src> + friend consteval bool + __polyfunc::__is_invoker_convertible() noexcept; + }; + +#undef _GLIBCXX_MOF_CV_REF +#undef _GLIBCXX_MOF_CV +#undef _GLIBCXX_MOF_REF +#undef _GLIBCXX_MOF_INV_QUALS + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std diff --git a/libstdc++-v3/include/bits/deque.tcc b/libstdc++-v3/include/bits/deque.tcc index dabb6ec..20b23ff 100644 --- a/libstdc++-v3/include/bits/deque.tcc +++ b/libstdc++-v3/include/bits/deque.tcc @@ -381,7 +381,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER const difference_type __back_capacity = (this->_M_impl._M_finish._M_last - this->_M_impl._M_finish._M_cur); - if (__front_capacity + __back_capacity < _S_buffer_size()) + if (size_type(__front_capacity + __back_capacity) < _S_buffer_size()) return false; return std::__shrink_to_fit_aux<deque>::_S_do_it(*this); @@ -664,7 +664,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER deque<_Tp, _Alloc>:: _M_emplace_aux(iterator __pos, _Args&&... __args) { - value_type __x_copy(std::forward<_Args>(__args)...); // XXX copy + // We should construct this temporary while the deque is + // in its current state in case something in __args... + // depends on that state before shuffling elements around. + _Temporary_value __tmp(this, std::forward<_Args>(__args)...); #else typename deque<_Tp, _Alloc>::iterator deque<_Tp, _Alloc>:: @@ -695,7 +698,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __pos = this->_M_impl._M_start + __index; _GLIBCXX_MOVE_BACKWARD3(__pos, __back2, __back1); } - *__pos = _GLIBCXX_MOVE(__x_copy); +#if __cplusplus >= 201103L + *__pos = std::move(__tmp._M_val()); +#else + *__pos = __x_copy; +#endif return __pos; } diff --git a/libstdc++-v3/include/bits/formatfwd.h b/libstdc++-v3/include/bits/formatfwd.h index 3fa01ad..883b772 100644 --- a/libstdc++-v3/include/bits/formatfwd.h +++ b/libstdc++-v3/include/bits/formatfwd.h @@ -71,12 +71,13 @@ namespace __format concept __char = same_as<_CharT, char>; #endif - enum _Align { + enum class _Align : unsigned char { _Align_default, _Align_left, _Align_right, _Align_centre, }; + using enum _Align; template<typename _CharT> struct _Spec; @@ -161,8 +162,39 @@ namespace __format using __maybe_const = __conditional_t<formattable<const _Tp, _CharT>, const _Tp, _Tp>; } + + // [format.range], formatting of ranges + // [format.range.fmtkind], variable template format_kind + enum class range_format { + disabled, + map, + set, + sequence, + string, + debug_string + }; + + /** @brief A constant determining how a range should be formatted. + * + * The primary template of `std::format_kind` cannot be instantiated. + * There is a partial specialization for input ranges and you can + * specialize the variable template for your own cv-unqualified types + * that satisfy the `ranges::input_range` concept. + * + * @since C++23 + */ + template<typename _Rg> + constexpr auto format_kind = []{ + static_assert(false, "cannot use primary template of 'std::format_kind'"); + return type_identity<_Rg>{}; + }(); #endif // format_ranges +#if __glibcxx_print >= 202403L + template<typename> + constexpr bool enable_nonlocking_formatter_optimization = false; +#endif + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std #endif // __glibcxx_format diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h index 8bcfb80..459b2f6 100644 --- a/libstdc++-v3/include/bits/forward_list.h +++ b/libstdc++-v3/include/bits/forward_list.h @@ -1046,7 +1046,7 @@ namespace __fwdlist void assign(_InputIterator __first, _InputIterator __last) { - if constexpr (is_assignable<_Tp, decltype(*__first)>::value) + if constexpr (is_assignable<_Tp&, decltype(*__first)>::value) { auto __prev = before_begin(); auto __curr = begin(); diff --git a/libstdc++-v3/include/bits/funcref_impl.h b/libstdc++-v3/include/bits/funcref_impl.h new file mode 100644 index 0000000..3fe2fb1 --- /dev/null +++ b/libstdc++-v3/include/bits/funcref_impl.h @@ -0,0 +1,202 @@ +// Implementation of std::function_ref -*- C++ -*- + +// Copyright The GNU Toolchain Authors. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file include/bits/funcref_impl.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _GLIBCXX_MOF_CV +# define _GLIBCXX_MOF_CV +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// @cond undocumented + namespace __polyfunc + { + template<bool _Noex, typename _Ret, typename _Class, typename... _Args> + struct __skip_first_arg<_Ret(_Class::*)(_Args...) _GLIBCXX_MOF_CV + noexcept(_Noex)> + { using type = _Ret(_Args...) noexcept(_Noex); }; + + template<bool _Noex, typename _Ret, typename _Class, typename... _Args> + struct __skip_first_arg<_Ret(_Class::*)(_Args...) _GLIBCXX_MOF_CV& + noexcept(_Noex)> + { using type = _Ret(_Args...) noexcept(_Noex); }; + } // namespace __polyfunc + /// @endcond + + /** + * @brief Non-owning polymorphic function wrapper. + * @ingroup functors + * @since C++26 + * @headerfile functional + * + * The `std::function_ref` class template is a non-owning call wrapper, + * that refers to a bound object. Using function_ref outside of the lifetime + * of the bound object has undefined behavior. + * + * It supports const-qualification and no-throw guarantees. The + * qualifications and exception-specification of the signature are respected + * when invoking the reference function. + */ + template<typename _Res, typename... _ArgTypes, bool _Noex> + class function_ref<_Res(_ArgTypes...) _GLIBCXX_MOF_CV + noexcept(_Noex)> + { + static_assert( + (std::__is_complete_or_unbounded(__type_identity<_ArgTypes>()) && ...), + "each parameter type must be a complete class"); + + using _Invoker = __polyfunc::_Invoker<_Noex, _Res, _ArgTypes...>; + using _Signature = _Invoker::_Signature; + + // [func.wrap.ref.ctor]/1 is-invokable-using + template<typename... _Tps> + static constexpr bool __is_invocable_using + = __conditional_t<_Noex, + is_nothrow_invocable_r<_Res, _Tps..., _ArgTypes...>, + is_invocable_r<_Res, _Tps..., _ArgTypes...>>::value; + + public: + /// Target and bound object is function pointed by parameter. + template<typename _Fn> + requires is_function_v<_Fn> && __is_invocable_using<_Fn*> + function_ref(_Fn* __fn) noexcept + { + __glibcxx_assert(__fn != nullptr); + _M_invoke = _Invoker::template _S_ptrs<_Fn*>(); + _M_init(__fn); + } + + /// Target and bound object is object referenced by parameter. + template<typename _Fn, typename _Vt = remove_reference_t<_Fn>> + requires (!is_same_v<remove_cv_t<_Vt>, function_ref>) + && (!is_member_pointer_v<_Vt>) + // We deviate from standard by having this condition, that forces + // function references to use _Fn* constructors. This simplies + // implementation and provide better diagnostic when used in + // constant expression (above constructor is not constexpr). + && (!is_function_v<_Vt>) + && __is_invocable_using<_Vt _GLIBCXX_MOF_CV&> + constexpr + function_ref(_Fn&& __f) noexcept + { + _M_invoke = _Invoker::template _S_ptrs<_Vt _GLIBCXX_MOF_CV&>(); + _M_init(std::addressof(__f)); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4256. Incorrect constrains for function_ref constructors from nontype + /// Target object is __fn. There is no bound object. + template<auto __fn> + requires __is_invocable_using<const decltype(__fn)&> + constexpr + function_ref(nontype_t<__fn>) noexcept + { + using _Fn = remove_cv_t<decltype(__fn)>; + if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>) + static_assert(__fn != nullptr); + + _M_invoke = &_Invoker::template _S_nttp<__fn>; + _M_ptrs._M_obj = nullptr; + } + + /// Target object is equivalent to std::bind_front<_fn>(std::ref(__ref)). + /// Bound object is object referenced by second parameter. + template<auto __fn, typename _Up, typename _Td = remove_reference_t<_Up>> + requires (!is_rvalue_reference_v<_Up&&>) + && __is_invocable_using<const decltype(__fn)&, _Td _GLIBCXX_MOF_CV&> + constexpr + function_ref(nontype_t<__fn>, _Up&& __ref) noexcept + { + using _Fn = remove_cv_t<decltype(__fn)>; + if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>) + static_assert(__fn != nullptr); + + if constexpr (is_member_pointer_v<_Fn> + && same_as<_Td, typename __inv_unwrap<_Td>::type>) + // N.B. invoking member pointer on lvalue produces the same effects, + // as invoking it on pointer to that lvalue. + _M_invoke = &_Invoker::template _S_bind_ptr<__fn, _Td _GLIBCXX_MOF_CV>; + else + _M_invoke = &_Invoker::template _S_bind_ref<__fn, _Td _GLIBCXX_MOF_CV&>; + _M_init(std::addressof(__ref)); + } + + /// Target object is equivalent to std::bind_front<_fn>(__ptr). + /// Bound object is object pointed by second parameter (if any). + template<auto __fn, typename _Td> + requires __is_invocable_using<const decltype(__fn)&, _Td _GLIBCXX_MOF_CV*> + constexpr + function_ref(nontype_t<__fn>, _Td _GLIBCXX_MOF_CV* __ptr) noexcept + { + using _Fn = remove_cv_t<decltype(__fn)>; + if constexpr (is_pointer_v<_Fn> || is_member_pointer_v<_Fn>) + static_assert(__fn != nullptr); + if constexpr (is_member_pointer_v<_Fn>) + __glibcxx_assert(__ptr != nullptr); + + _M_invoke = &_Invoker::template _S_bind_ptr<__fn, _Td _GLIBCXX_MOF_CV>; + _M_init(__ptr); + } + + template<typename _Tp> + requires (!is_same_v<_Tp, function_ref>) + && (!is_pointer_v<_Tp>) && (!__is_nontype_v<_Tp>) + function_ref& + operator=(_Tp) = delete; + + /** Invoke the target object. + * + * The bound object will be invoked using the supplied arguments, + * and as const or non-const, as dictated by the template arguments + * of the `function_ref` specialization. + */ + _Res + operator()(_ArgTypes... __args) const noexcept(_Noex) + { return _M_invoke(_M_ptrs, std::forward<_ArgTypes>(__args)...); } + + private: + template<typename _Tp> + constexpr void + _M_init(_Tp* __ptr) noexcept + { + if constexpr (is_function_v<_Tp>) + _M_ptrs._M_func = reinterpret_cast<void(*)()>(__ptr); + else + _M_ptrs._M_obj = __ptr; + } + + typename _Invoker::__ptrs_func_t _M_invoke; + __polyfunc::_Ptrs _M_ptrs; + }; + +#undef _GLIBCXX_MOF_CV + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std diff --git a/libstdc++-v3/include/bits/functional_hash.h b/libstdc++-v3/include/bits/functional_hash.h index e84c9ee..8456089 100644 --- a/libstdc++-v3/include/bits/functional_hash.h +++ b/libstdc++-v3/include/bits/functional_hash.h @@ -199,6 +199,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_3 unsigned) #endif +#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ + // In strict modes __GLIBCXX_TYPE_INT_N_0 is not defined for __int128, + // but we want to always treat signed/unsigned __int128 as integral types. + __extension__ + _Cxx_hashtable_define_trivial_hash(__int128) + __extension__ + _Cxx_hashtable_define_trivial_hash(__int128 unsigned) +#endif + #undef _Cxx_hashtable_define_trivial_hash struct _Hash_impl diff --git a/libstdc++-v3/include/bits/funcwrap.h b/libstdc++-v3/include/bits/funcwrap.h new file mode 100644 index 0000000..67fd591 --- /dev/null +++ b/libstdc++-v3/include/bits/funcwrap.h @@ -0,0 +1,622 @@ +// Implementation of std::move_only_function, std::copyable_function +// and std::function_ref -*- C++ -*- + +// Copyright The GNU Toolchain Authors. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file include/bits/funcwrap.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _GLIBCXX_FUNCWRAP_H +#define _GLIBCXX_FUNCWRAP_H 1 + +#ifdef _GLIBCXX_SYSHDR +#pragma GCC system_header +#endif + +#include <bits/version.h> + +#if __glibcxx_move_only_function || __glibcxx_copyable_function || __glibcxx_function_ref + +#include <bits/invoke.h> +#include <bits/utility.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// @cond undocumented + template<typename _Tp> + inline constexpr bool __is_polymorphic_function_v = false; + + namespace __polyfunc + { + union _Ptrs + { + const void* _M_obj; + void (*_M_func)(); + }; + + template<typename _Tp> + [[__gnu__::__always_inline__]] + constexpr auto* + __cast_to(_Ptrs __ptrs) noexcept + { + using _Td = remove_reference_t<_Tp>; + if constexpr (is_function_v<_Td>) + return reinterpret_cast<_Td*>(__ptrs._M_func); + else if constexpr (is_const_v<_Td>) + return static_cast<_Td*>(__ptrs._M_obj); + else + return static_cast<_Td*>(const_cast<void*>(__ptrs._M_obj)); + } + + struct _Storage + { + void* _M_addr() noexcept { return &_M_bytes[0]; } + void const* _M_addr() const noexcept { return &_M_bytes[0]; } + + template<typename _Tp> + static consteval bool + _S_stored_locally() noexcept + { + return sizeof(_Tp) <= sizeof(_Storage) + && alignof(_Tp) <= alignof(_Storage) + && is_nothrow_move_constructible_v<_Tp>; + } + + template<typename _Tp, typename... _Args> + static consteval bool + _S_nothrow_init() noexcept + { + if constexpr (_S_stored_locally<_Tp>()) + return is_nothrow_constructible_v<_Tp, _Args...>; + return false; + } + + template<typename _Tp, typename... _Args> + void + _M_init(_Args&&... __args) noexcept(_S_nothrow_init<_Tp, _Args...>()) + { + if constexpr (is_function_v<remove_pointer_t<_Tp>>) + { + static_assert( sizeof...(__args) <= 1 ); + // __args can have up to one element, returns nullptr if empty. + _Tp __func = (nullptr, ..., __args); + _M_ptrs._M_func = reinterpret_cast<void(*)()>(__func); + } + else if constexpr (!_S_stored_locally<_Tp>()) + _M_ptrs._M_obj = new _Tp(std::forward<_Args>(__args)...); + else + ::new (_M_addr()) _Tp(std::forward<_Args>(__args)...); + } + + // We want to have enough space to store a simple delegate type. + struct _Delegate { void (_Storage::*__pfm)(); _Storage* __obj; }; + union { + _Ptrs _M_ptrs; + alignas(_Delegate) alignas(void(*)()) + unsigned char _M_bytes[sizeof(_Delegate)]; + }; + }; + + template<bool _Noex, typename _Ret, typename... _Args> + struct _Base_invoker + { + using _Signature = _Ret(*)(_Args...) noexcept(_Noex); + + using __storage_func_t = _Ret(*)(const _Storage&, _Args...) noexcept(_Noex); + template<typename _Tp> + static consteval __storage_func_t + _S_storage() + { return &_S_call_storage<_Adjust_target<_Tp>>; } + + using __ptrs_func_t = _Ret(*)(_Ptrs, _Args...) noexcept(_Noex); + template<typename _Tp> + static consteval __ptrs_func_t + _S_ptrs() + { return &_S_call_ptrs<_Adjust_target<_Tp>>; } + +#ifdef __glibcxx_function_ref // C++ >= 26 + template<auto __fn> + static _Ret + _S_nttp(_Ptrs, _Args... __args) noexcept(_Noex) + { return std::__invoke_r<_Ret>(__fn, std::forward<_Args>(__args)...); } + + template<auto __fn, typename _Tp> + static _Ret + _S_bind_ptr(_Ptrs __ptrs, _Args... __args) noexcept(_Noex) + { + auto* __p = __polyfunc::__cast_to<_Tp>(__ptrs); + return std::__invoke_r<_Ret>(__fn, __p, + std::forward<_Args>(__args)...); + } + + template<auto __fn, typename _Ref> + static _Ret + _S_bind_ref(_Ptrs __ptrs, _Args... __args) noexcept(_Noex) + { + auto* __p = __polyfunc::__cast_to<_Ref>(__ptrs); + return std::__invoke_r<_Ret>(__fn, static_cast<_Ref>(*__p), + std::forward<_Args>(__args)...); + } +#endif // __glibcxx_function_ref + + private: + template<typename _Tp, typename _Td = remove_cvref_t<_Tp>> + using _Adjust_target = + __conditional_t<is_pointer_v<_Td> || is_member_pointer_v<_Td>, _Td, _Tp>; + + template<typename _Tp> + static _Ret + _S_call_storage(const _Storage& __ref, _Args... __args) noexcept(_Noex) + { + _Ptrs __ptrs; + if constexpr (is_function_v<remove_pointer_t<_Tp>>) + __ptrs._M_func = __ref._M_ptrs._M_func; + else if constexpr (!_Storage::_S_stored_locally<remove_cvref_t<_Tp>>()) + __ptrs._M_obj = __ref._M_ptrs._M_obj; + else + __ptrs._M_obj = __ref._M_addr(); + return _S_call_ptrs<_Tp>(__ptrs, std::forward<_Args>(__args)...); + } + + template<typename _Tp> + static _Ret + _S_call_ptrs(_Ptrs __ptrs, _Args... __args) noexcept(_Noex) + { + if constexpr (is_function_v<remove_pointer_t<_Tp>>) + return std::__invoke_r<_Ret>(reinterpret_cast<_Tp>(__ptrs._M_func), + std::forward<_Args>(__args)...); + else + { + auto* __p = __polyfunc::__cast_to<_Tp>(__ptrs); + return std::__invoke_r<_Ret>(static_cast<_Tp>(*__p), + std::forward<_Args>(__args)...); + } + } + }; + + template<typename _Tp> + consteval bool + __pass_by_value() + { + // n.b. sizeof(Incomplete&) is ill-formed for incomplete types, + // so we check is_reference_v first. + if constexpr (is_reference_v<_Tp> || is_scalar_v<_Tp>) + return true; + else + // n.b. we already asserted that types are complete in wrappers, + // avoid triggering additional errors from this function. + if constexpr (std::__is_complete_or_unbounded(__type_identity<_Tp>())) + if constexpr (sizeof(_Tp) <= 2 * sizeof(void*)) + return is_trivially_move_constructible_v<_Tp> + && is_trivially_destructible_v<_Tp>; + return false; + } + + template<typename _Tp> + using __param_t = __conditional_t<__pass_by_value<_Tp>(), _Tp, _Tp&&>; + + template<bool _Noex, typename _Ret, typename... _Args> + using _Invoker = _Base_invoker<_Noex, remove_cv_t<_Ret>, __param_t<_Args>...>; + + template<typename _Func> + auto& + __invoker_of(_Func& __f) noexcept + { return __f._M_invoke; } + + template<typename _Func> + auto& + __base_of(_Func& __f) noexcept + { return static_cast<__like_t<_Func&, typename _Func::_Base>>(__f); } + + template<typename _Src, typename _Dst> + consteval bool + __is_invoker_convertible() noexcept + { + if constexpr (requires { typename _Src::_Signature; }) + return is_convertible_v<typename _Src::_Signature, + typename _Dst::_Signature>; + else + return false; + } + +#if __glibcxx_move_only_function || __glibcxx_copyable_function + struct _Manager + { + enum class _Op + { + // saves address of entity in *__src to __target._M_ptrs, + _Address, + // moves entity stored in *__src to __target, __src becomes empty + _Move, + // copies entity stored in *__src to __target, supported only if + // _ProvideCopy is specified. + _Copy, + // destroys entity stored in __target, __src is ignoring + _Destroy, + }; + + // A function that performs operation __op on the __target and possibly __src. + using _Func = void (*)(_Op __op, _Storage& __target, const _Storage* __src); + + // The no-op manager function for objects with no target. + static void _S_empty(_Op, _Storage&, const _Storage*) noexcept { } + + template<bool _ProvideCopy, typename _Tp> + consteval static auto + _S_select() + { + if constexpr (is_function_v<remove_pointer_t<_Tp>>) + return &_S_func; + else if constexpr (!_Storage::_S_stored_locally<_Tp>()) + return &_S_ptr<_ProvideCopy, _Tp>; + else if constexpr (is_trivially_copyable_v<_Tp>) + return &_S_trivial; + else + return &_S_local<_ProvideCopy, _Tp>; + } + + private: + static void + _S_func(_Op __op, _Storage& __target, const _Storage* __src) noexcept + { + switch (__op) + { + case _Op::_Address: + case _Op::_Move: + case _Op::_Copy: + __target._M_ptrs._M_func = __src->_M_ptrs._M_func; + return; + case _Op::_Destroy: + return; + } + } + + static void + _S_trivial(_Op __op, _Storage& __target, const _Storage* __src) noexcept + { + switch (__op) + { + case _Op::_Address: + __target._M_ptrs._M_obj = __src->_M_addr(); + return; + case _Op::_Move: + case _Op::_Copy: + // N.B. Creating _Storage starts lifetime of _M_bytes char array, + // that implicitly creates, amongst other, all possible trivially + // copyable objects, so we copy any object present in __src._M_bytes. + ::new (&__target) _Storage(*__src); + return; + case _Op::_Destroy: + return; + } + } + + template<bool _Provide_copy, typename _Tp> + static void + _S_local(_Op __op, _Storage& __target, const _Storage* __src) + noexcept(!_Provide_copy) + { + switch (__op) + { + case _Op::_Address: + __target._M_ptrs._M_obj = __src->_M_addr(); + return; + case _Op::_Move: + { + _Tp* __obj = static_cast<_Tp*>(const_cast<void*>(__src->_M_addr())); + ::new(__target._M_addr()) _Tp(std::move(*__obj)); + __obj->~_Tp(); + } + return; + case _Op::_Destroy: + static_cast<_Tp*>(__target._M_addr())->~_Tp(); + return; + case _Op::_Copy: + if constexpr (_Provide_copy) + { + auto* __obj = static_cast<const _Tp*>(__src->_M_addr()); + ::new (__target._M_addr()) _Tp(*__obj); + return; + } + __builtin_unreachable(); + } + } + + template<bool _Provide_copy, typename _Tp> + static void + _S_ptr(_Op __op, _Storage& __target, const _Storage* __src) + noexcept(!_Provide_copy) + { + switch (__op) + { + case _Op::_Address: + case _Op::_Move: + __target._M_ptrs._M_obj = __src->_M_ptrs._M_obj; + return; + case _Op::_Destroy: + delete static_cast<const _Tp*>(__target._M_ptrs._M_obj); + return; + case _Op::_Copy: + if constexpr (_Provide_copy) + { + auto* __obj = static_cast<const _Tp*>(__src->_M_ptrs._M_obj); + __target._M_ptrs._M_obj = new _Tp(*__obj); + return; + } + __builtin_unreachable(); + } + } + }; + + class _Mo_base + { + protected: + _Mo_base() noexcept + : _M_manage(_Manager::_S_empty) + { } + + _Mo_base(_Mo_base&& __x) noexcept + { _M_move(__x); } + + template<typename _Tp, typename... _Args> + static consteval bool + _S_nothrow_init() noexcept + { return _Storage::_S_nothrow_init<_Tp, _Args...>(); } + + template<typename _Tp, typename... _Args> + void + _M_init(_Args&&... __args) + noexcept(_S_nothrow_init<_Tp, _Args...>()) + { + _M_storage._M_init<_Tp>(std::forward<_Args>(__args)...); + _M_manage = _Manager::_S_select<false, _Tp>(); + } + + void + _M_move(_Mo_base& __x) noexcept + { + using _Op = _Manager::_Op; + _M_manage = std::__exchange(__x._M_manage, _Manager::_S_empty); + _M_manage(_Op::_Move, _M_storage, &__x._M_storage); + } + + _Mo_base& + operator=(_Mo_base&& __x) noexcept + { + _M_destroy(); + _M_move(__x); + return *this; + } + + void + _M_reset() noexcept + { + _M_destroy(); + _M_manage = _Manager::_S_empty; + } + + void _M_destroy() noexcept + { _M_manage(_Manager::_Op::_Destroy, _M_storage, nullptr); } + + ~_Mo_base() + { _M_destroy(); } + + void + swap(_Mo_base& __x) noexcept + { + using _Op = _Manager::_Op; + // Order of operations here is more efficient if __x is empty. + _Storage __s; + __x._M_manage(_Op::_Move, __s, &__x._M_storage); + _M_manage(_Op::_Move, __x._M_storage, &_M_storage); + __x._M_manage(_Op::_Move, _M_storage, &__s); + std::swap(_M_manage, __x._M_manage); + } + + _Manager::_Func _M_manage; + _Storage _M_storage; + }; +#endif // __glibcxx_copyable_function || __glibcxx_copyable_function +} // namespace __polyfunc + /// @endcond + +#ifdef __glibcxx_move_only_function // C++ >= 23 && HOSTED + template<typename... _Signature> + class move_only_function; // not defined + + /// @cond undocumented + template<typename _Tp> + constexpr bool __is_polymorphic_function_v<move_only_function<_Tp>> = true; + + namespace __detail::__variant + { + template<typename> struct _Never_valueless_alt; // see <variant> + + // Provide the strong exception-safety guarantee when emplacing a + // move_only_function into a variant. + template<typename... _Signature> + struct _Never_valueless_alt<std::move_only_function<_Signature...>> + : true_type + { }; + } // namespace __detail::__variant + /// @endcond +#endif // __glibcxx_move_only_function + +#ifdef __glibcxx_copyable_function // C++ >= 26 && HOSTED + /// @cond undocumented + namespace __polyfunc + { + class _Cpy_base : public _Mo_base + { + protected: + _Cpy_base() = default; + + template<typename _Tp, typename... _Args> + void + _M_init(_Args&&... __args) + noexcept(_S_nothrow_init<_Tp, _Args...>()) + { + _M_storage._M_init<_Tp>(std::forward<_Args>(__args)...); + _M_manage = _Manager::_S_select<true, _Tp>(); + } + + void + _M_copy(_Cpy_base const& __x) + { + using _Op = _Manager::_Op; + __x._M_manage(_Op::_Copy, _M_storage, &__x._M_storage); + _M_manage = __x._M_manage; + } + + _Cpy_base(_Cpy_base&&) = default; + + _Cpy_base(_Cpy_base const& __x) + { _M_copy(__x); } + + _Cpy_base& + operator=(_Cpy_base&&) = default; + + _Cpy_base& + // Needs to use copy and swap for exception guarantees. + operator=(_Cpy_base const&) = delete; + }; + } // namespace __polyfunc + /// @endcond + + template<typename... _Signature> + class copyable_function; // not defined + + template<typename _Tp> + constexpr bool __is_polymorphic_function_v<copyable_function<_Tp>> = true; + + namespace __detail::__variant + { + template<typename> struct _Never_valueless_alt; // see <variant> + + // Provide the strong exception-safety guarantee when emplacing a + // copyable_function into a variant. + template<typename... _Signature> + struct _Never_valueless_alt<std::copyable_function<_Signature...>> + : true_type + { }; + } // namespace __detail::__variant +#endif // __glibcxx_copyable_function + +#ifdef __glibcxx_function_ref // C++ >= 26 + /// @cond undocumented + namespace __polyfunc + { + template<typename _Sig> + struct __skip_first_arg; + + // Additional partial specializations are defined in bits/funcref_impl.h + template<bool _Noex, typename _Ret, typename _Arg, typename... _Args> + struct __skip_first_arg<_Ret(*)(_Arg, _Args...) noexcept(_Noex)> + { using type = _Ret(_Args...) noexcept(_Noex); }; + + // Returns a function pointer to signature to be used with function_ref, or void. + template<typename _Fn, typename _Tr> + consteval auto + __deduce_funcref() + { + if constexpr (is_member_object_pointer_v<_Fn>) + { + if constexpr (is_invocable_v<_Fn, _Tr>) + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4425. CTAD function_ref from data member pointer should produce + // noexcept signature + return static_cast<invoke_result_t<_Fn, _Tr>(*)() noexcept>(nullptr); + } + else if constexpr (requires { typename __skip_first_arg<_Fn>::type; }) + return static_cast<__skip_first_arg<_Fn>::type*>(nullptr); + } + } // namespace __polyfunc + /// @endcond + + template<typename... _Signature> + class function_ref; // not defined + + template<typename _Fn> + requires is_function_v<_Fn> + function_ref(_Fn*) -> function_ref<_Fn>; + + template<auto __f, class _Fn = remove_pointer_t<decltype(__f)>> + requires is_function_v<_Fn> + function_ref(nontype_t<__f>) -> function_ref<_Fn>; + + template<auto __f, typename _Tp, + typename _SignaturePtr = + decltype(__polyfunc::__deduce_funcref<decltype(__f), _Tp&>())> + requires (!is_void_v<_SignaturePtr>) + function_ref(nontype_t<__f>, _Tp&&) + -> function_ref<remove_pointer_t<_SignaturePtr>>; + +#endif // __glibcxx_function_ref + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#ifdef __glibcxx_move_only_function // C++ >= 23 && HOSTED +#include "mofunc_impl.h" +#define _GLIBCXX_MOF_CV const +#include "mofunc_impl.h" +#define _GLIBCXX_MOF_REF & +#include "mofunc_impl.h" +#define _GLIBCXX_MOF_REF && +#include "mofunc_impl.h" +#define _GLIBCXX_MOF_CV const +#define _GLIBCXX_MOF_REF & +#include "mofunc_impl.h" +#define _GLIBCXX_MOF_CV const +#define _GLIBCXX_MOF_REF && +#include "mofunc_impl.h" +#endif // __glibcxx_move_only_function + +#ifdef __glibcxx_copyable_function // C++ >= 26 && HOSTED +#include "cpyfunc_impl.h" +#define _GLIBCXX_MOF_CV const +#include "cpyfunc_impl.h" +#define _GLIBCXX_MOF_REF & +#include "cpyfunc_impl.h" +#define _GLIBCXX_MOF_REF && +#include "cpyfunc_impl.h" +#define _GLIBCXX_MOF_CV const +#define _GLIBCXX_MOF_REF & +#include "cpyfunc_impl.h" +#define _GLIBCXX_MOF_CV const +#define _GLIBCXX_MOF_REF && +#include "cpyfunc_impl.h" +#endif // __glibcxx_copyable_function + +#ifdef __glibcxx_function_ref // C++ >= 26 +#include "funcref_impl.h" +#define _GLIBCXX_MOF_CV const +#include "funcref_impl.h" +#endif // __glibcxx_function_ref + +#endif // move_only_function || copyable_function || function_ref +#endif // _GLIBCXX_FUNCWRAP_H diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h index 20f9bd9..06cc51a 100644 --- a/libstdc++-v3/include/bits/hashtable.h +++ b/libstdc++-v3/include/bits/hashtable.h @@ -38,7 +38,7 @@ #include <bits/enable_special_members.h> #include <bits/stl_algobase.h> // fill_n, is_permutation #include <bits/stl_function.h> // __has_is_transparent_t -#if __cplusplus > 201402L +#ifdef __glibcxx_node_extract // >= C++17 && HOSTED # include <bits/node_handle.h> #endif @@ -349,7 +349,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using size_type = typename __hashtable_base::size_type; using difference_type = typename __hashtable_base::difference_type; -#if __cplusplus > 201402L +#ifdef __glibcxx_node_extract // >= C++17 && HOSTED using node_type = _Node_handle<_Key, _Value, __node_alloc_type>; using insert_return_type = _Node_insert_return<iterator, node_type>; #endif @@ -477,15 +477,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static constexpr bool _S_nothrow_move() { -#if __cplusplus <= 201402L +#if __cpp_constexpr >= 201304 // >= C++14 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr + if constexpr (_No_realloc) + if constexpr (is_nothrow_copy_constructible<_Hash>::value) + return is_nothrow_copy_constructible<_Equal>::value; + return false; +# pragma GCC diagnostic pop +#else // In C++11 a constexpr function must be a single statement. return __and_<__bool_constant<_No_realloc>, is_nothrow_copy_constructible<_Hash>, is_nothrow_copy_constructible<_Equal>>::value; -#else - if constexpr (_No_realloc) - if constexpr (is_nothrow_copy_constructible<_Hash>()) - return is_nothrow_copy_constructible<_Equal>(); - return false; #endif } @@ -1928,7 +1931,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION -> const_iterator { return const_iterator(_M_locate(__k)); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Key, typename _Value, typename _Alloc, typename _ExtractKey, typename _Equal, typename _Hash, typename _RangeHash, typename _Unused, @@ -1976,7 +1979,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::size_t __bkt = _M_bucket_index(__code); return const_iterator(_M_find_node_tr(__bkt, __k, __code)); } -#endif +#endif // C++20 __glibcxx_generic_unordered_lookup template<typename _Key, typename _Value, typename _Alloc, typename _ExtractKey, typename _Equal, @@ -2004,7 +2007,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __result; } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Key, typename _Value, typename _Alloc, typename _ExtractKey, typename _Equal, typename _Hash, typename _RangeHash, typename _Unused, @@ -2049,7 +2052,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __result; } -#endif +#endif // C++20 __glibcxx_generic_unordered_lookup template<typename _Key, typename _Value, typename _Alloc, typename _ExtractKey, typename _Equal, @@ -2099,7 +2102,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return { __beg, __ite }; } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Key, typename _Value, typename _Alloc, typename _ExtractKey, typename _Equal, typename _Hash, typename _RangeHash, typename _Unused, @@ -2187,7 +2190,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return { __beg, __ite }; } -#endif +#endif // C++20 __glibcxx_generic_unordered_lookup // Find the node before the one whose key compares equal to k in the bucket // bkt. Return nullptr if no node is found. @@ -2963,7 +2966,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #pragma GCC diagnostic pop -#if __cplusplus > 201402L +#ifdef __glibcxx_node_extract // >= C++17 && HOSTED template<typename, typename, typename> class _Hash_merge_helper { }; #endif // C++17 diff --git a/libstdc++-v3/include/bits/indirect.h b/libstdc++-v3/include/bits/indirect.h new file mode 100644 index 0000000..2df46cc --- /dev/null +++ b/libstdc++-v3/include/bits/indirect.h @@ -0,0 +1,836 @@ +// Vocabulary Types for Composite Class Design -*- C++ -*- + +// Copyright The GNU Toolchain Authors. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file include/bits/indirect.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _GLIBCXX_INDIRECT_H +#define _GLIBCXX_INDIRECT_H 1 + +#pragma GCC system_header + +#include <bits/version.h> + +#if __glibcxx_indirect || __glibcxx_polymorphic // >= C++26 +#include <compare> +#include <initializer_list> +#include <bits/allocator.h> +#include <bits/alloc_traits.h> +#include <bits/allocated_ptr.h> // __allocate_guarded +#include <bits/uses_allocator.h> // allocator_arg_t +#include <bits/utility.h> // __is_in_place_type_v +#include <bits/functional_hash.h> // hash +#include <bits/memory_resource.h> // polymorphic_allocator + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __glibcxx_indirect + template<typename _Tp, typename _Alloc = allocator<_Tp>> + class indirect; + + template<typename _Tp> + constexpr bool __is_indirect = false; + template<typename _Tp, typename _Alloc> + constexpr bool __is_indirect<indirect<_Tp, _Alloc>> = true; + +#if _GLIBCXX_HOSTED + namespace pmr + { + template<typename _Tp> + using indirect = indirect<_Tp, polymorphic_allocator<_Tp>>; + } +#endif + + // [indirect], class template indirect + template<typename _Tp, typename _Alloc> + class indirect + { + static_assert(is_object_v<_Tp>); + static_assert(!is_array_v<_Tp>); + static_assert(!is_same_v<_Tp, in_place_t>); + static_assert(!__is_in_place_type_v<_Tp>); + static_assert(!is_const_v<_Tp> && !is_volatile_v<_Tp>); + + using _ATraits = allocator_traits<_Alloc>; + static_assert(is_same_v<_Tp, typename _ATraits::value_type>); + + public: + using value_type = _Tp; + using allocator_type = _Alloc; + using pointer = typename allocator_traits<_Alloc>::pointer; + using const_pointer = typename allocator_traits<_Alloc>::const_pointer; + + constexpr explicit + indirect() requires is_default_constructible_v<_Alloc> + : _M_objp(_M_make_obj_chk()) + { } + + constexpr explicit + indirect(allocator_arg_t, const _Alloc& __a) + : _M_alloc(__a), _M_objp(_M_make_obj_chk()) + { } + + constexpr + indirect(const indirect& __o) + : indirect(allocator_arg, + _ATraits::select_on_container_copy_construction(__o._M_alloc), + __o) + { } + + constexpr + indirect(allocator_arg_t, const _Alloc& __a, const indirect& __other) + : _M_alloc(__a) + { + if (__other._M_objp) + _M_objp = _M_make_obj_chk(__other.__get()); + else + _M_objp = nullptr; + } + + constexpr + indirect(indirect&& __other) noexcept + : _M_alloc(std::move(__other._M_alloc)), + _M_objp(std::__exchange(__other._M_objp, nullptr)) + { } + + constexpr + indirect(allocator_arg_t, const _Alloc& __a, + indirect&& __other) noexcept(_ATraits::is_always_equal::value) + : _M_alloc(__a), + _M_objp(std::__exchange(__other._M_objp, nullptr)) + { + if constexpr (!_ATraits::is_always_equal::value) + if (_M_objp && _M_alloc != __other._M_alloc) + { + static_assert(sizeof(_Tp) != 0, "must be a complete type"); + + // _M_alloc cannot free _M_objp, give it back to __other. + __other._M_objp = std::__exchange(_M_objp, nullptr); + // And create a new object that can be freed by _M_alloc. + _M_objp = _M_make_obj(std::move(*__other._M_objp)); + } + } + + template<typename _Up = _Tp> + requires (!is_same_v<remove_cvref_t<_Up>, in_place_t>) + && (!is_same_v<remove_cvref_t<_Up>, indirect>) + && is_constructible_v<_Tp, _Up> + && is_default_constructible_v<_Alloc> + constexpr explicit + indirect(_Up&& __u) + : _M_objp(_M_make_obj(std::forward<_Up>(__u))) + { } + + template<typename _Up = _Tp> + requires (!is_same_v<remove_cvref_t<_Up>, in_place_t>) + && (!is_same_v<remove_cvref_t<_Up>, indirect>) + && is_constructible_v<_Tp, _Up> + constexpr explicit + indirect(allocator_arg_t, const _Alloc& __a, _Up&& __u) + : _M_alloc(__a), _M_objp(_M_make_obj(std::forward<_Up>(__u))) + { } + + template<typename... _Us> + requires is_constructible_v<_Tp, _Us...> + && is_default_constructible_v<_Alloc> + constexpr explicit + indirect(in_place_t, _Us&&... __us) + : _M_objp(_M_make_obj(std::forward<_Us>(__us)...)) + { } + + template<typename... _Us> + requires is_constructible_v<_Tp, _Us...> + constexpr explicit + indirect(allocator_arg_t, const _Alloc& __a, in_place_t, _Us&&... __us) + : _M_alloc(__a), + _M_objp(_M_make_obj(std::forward<_Us>(__us)...)) + { } + + template<typename _Ip, typename... _Us> + requires is_constructible_v<_Tp, initializer_list<_Ip>&, _Us...> + && is_default_constructible_v<_Alloc> + constexpr explicit + indirect(in_place_t, initializer_list<_Ip> __il, _Us&&... __us) + : _M_objp(_M_make_obj(__il, std::forward<_Us>(__us)...)) + { } + + template<typename _Ip, typename... _Us> + requires is_constructible_v<_Tp, initializer_list<_Ip>&, _Us...> + constexpr explicit + indirect(allocator_arg_t, const _Alloc& __a, + in_place_t, initializer_list<_Ip> __il, _Us&&... __us) + : _M_alloc(__a), + _M_objp(_M_make_obj(__il, std::forward<_Us>(__us)...)) + { } + + constexpr ~indirect() + { + static_assert(sizeof(_Tp) != 0, "must be a complete type"); + _M_reset(nullptr); + } + + constexpr indirect& + operator=(const indirect& __other) + { + static_assert(is_copy_assignable_v<_Tp>); + static_assert(is_copy_constructible_v<_Tp>); + + if (__builtin_addressof(__other) == this) [[unlikely]] + return *this; + + constexpr bool __pocca + = _ATraits::propagate_on_container_copy_assignment::value; + + pointer __ptr = nullptr; + if (__other._M_objp) + { + if (_ATraits::is_always_equal::value + || _M_alloc == __other._M_alloc) + { + if (_M_objp) + { + *_M_objp = __other.__get(); + if constexpr (__pocca) + _M_alloc = __other._M_alloc; + return *this; + } + } + const indirect& __x = __pocca ? __other : *this; + __ptr = __x._M_make_obj(__other.__get()); + } + + _M_reset(__ptr); + + if constexpr (__pocca) + _M_alloc = __other._M_alloc; + + return *this; + } + + constexpr indirect& + operator=(indirect&& __other) + noexcept(_ATraits::propagate_on_container_move_assignment::value + || _ATraits::is_always_equal::value) + { + // N5008 says is_copy_constructible_v<T> here, but that seems wrong. + // We only require move-constructible, and only for unequal allocators. + + if (__builtin_addressof(__other) == this) [[unlikely]] + return *this; + + constexpr bool __pocma + = _ATraits::propagate_on_container_move_assignment::value; + + pointer __ptr = nullptr; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4251. Move assignment for indirect unnecessarily requires copy construction + if constexpr (_ATraits::is_always_equal::value || __pocma) + __ptr = std::__exchange(__other._M_objp, nullptr); + else if (_M_alloc == __other._M_alloc) + __ptr = std::__exchange(__other._M_objp, nullptr); + else if (__other._M_objp) + { + static_assert(is_move_constructible_v<_Tp>); + __ptr = _M_make_obj(std::move(*__other._M_objp)); + } + + _M_reset(__ptr); + + if constexpr (__pocma) + _M_alloc = std::move(__other._M_alloc); + + return *this; + } + + template<typename _Up = _Tp> + requires (!is_same_v<remove_cvref_t<_Up>, indirect>) + && is_constructible_v<_Tp, _Up> && is_assignable_v<_Tp&, _Up> + constexpr indirect& + operator=(_Up&& __u) + { + if (_M_objp == nullptr) + _M_objp = _M_make_obj(std::forward<_Up>(__u)); + else + *_M_objp = std::forward<_Up>(__u); + + return *this; + } + + template<typename _Self> + constexpr auto&& + operator*(this _Self&& __self) noexcept + { + // n.b. [allocator.requirements.general] p22 implies + // dereferencing const pointer is same as pointer + const indirect& __iself = (const indirect&)__self; + __glibcxx_assert(__iself._M_objp != nullptr); + return std::forward_like<_Self>(*__iself._M_objp); + } + + constexpr const_pointer + operator->() const noexcept + { + // Do we want to enforce this? __glibcxx_assert(_M_objp != nullptr); + return _M_objp; + } + + constexpr pointer + operator->() noexcept + { + // Do we want to enforce this? __glibcxx_assert(_M_objp != nullptr); + return _M_objp; + } + + constexpr bool + valueless_after_move() const noexcept { return _M_objp == nullptr; } + + constexpr allocator_type + get_allocator() const noexcept { return _M_alloc; } + + constexpr void + swap(indirect& __other) + noexcept(_ATraits::propagate_on_container_swap::value + || _ATraits::is_always_equal::value) + { + using std::swap; + swap(_M_objp, __other._M_objp); + if constexpr (_ATraits::propagate_on_container_swap::value) + swap(_M_alloc, __other._M_alloc); + else if constexpr (!_ATraits::is_always_equal::value) + __glibcxx_assert(_M_alloc == __other._M_alloc); + } + + friend constexpr void + swap(indirect& __lhs, indirect& __rhs) + noexcept(_ATraits::propagate_on_container_swap::value + || _ATraits::is_always_equal::value) + { __lhs.swap(__rhs); } + + template<typename _Up, typename _Alloc2> + requires requires (const _Tp& __t, const _Up& __u) { __t == __u; } + friend constexpr bool + operator==(const indirect& __lhs, const indirect<_Up, _Alloc2>& __rhs) + noexcept(noexcept(*__lhs == *__rhs)) + { + if (!__lhs._M_objp || !__rhs._M_objp) + return bool(__lhs._M_objp) == bool(__rhs._M_objp); + else + return __lhs.__get() == __rhs.__get(); + } + + template<typename _Up> + requires (!__is_indirect<_Up>) // See PR c++/99599 + && requires (const _Tp& __t, const _Up& __u) { __t == __u; } + friend constexpr bool + operator==(const indirect& __lhs, const _Up& __rhs) + noexcept(noexcept(*__lhs == __rhs)) + { + if (!__lhs._M_objp) + return false; + else + return __lhs.__get() == __rhs; + } + + template<typename _Up, typename _Alloc2> + friend constexpr __detail::__synth3way_t<_Tp, _Up> + operator<=>(const indirect& __lhs, const indirect<_Up, _Alloc2>& __rhs) + noexcept(noexcept(__detail::__synth3way(*__lhs, *__rhs))) + { + if (!__lhs._M_objp || !__rhs._M_objp) + return bool(__lhs._M_objp) <=> bool(__rhs._M_objp); + else + return __detail::__synth3way(__lhs.__get(), __rhs.__get()); + } + + template<typename _Up> + requires (!__is_indirect<_Up>) // See PR c++/99599 + friend constexpr __detail::__synth3way_t<_Tp, _Up> + operator<=>(const indirect& __lhs, const _Up& __rhs) + noexcept(noexcept(__detail::__synth3way(*__lhs, __rhs))) + { + if (!__lhs._M_objp) + return strong_ordering::less; + else + return __detail::__synth3way(__lhs.__get(), __rhs); + } + + private: + template<typename, typename> friend class indirect; + + constexpr void + _M_reset(pointer __ptr) noexcept + { + if (_M_objp) + { + _ATraits::destroy(_M_alloc, std::to_address(_M_objp)); + _ATraits::deallocate(_M_alloc, _M_objp, 1); + } + _M_objp = __ptr; + } + + template<typename... _Args> + constexpr pointer + _M_make_obj(_Args&&... __args) const + { + _Scoped_allocation __sa(_M_alloc, in_place, + std::forward<_Args>(__args)...); + return __sa.release(); + } + + // Enforces is_constructible check and then calls _M_make_obj. + template<typename... _Args> + [[__gnu__::__always_inline__]] + constexpr pointer + _M_make_obj_chk(_Args&&... __args) const + { + static_assert(is_constructible_v<_Tp, _Args...>); + return _M_make_obj(std::forward<_Args>(__args)...); + } + + // Always-const accessor that avoids ADL for operator*. + // This can be preferable to using *_M_objp because that might give _Tp&. + // This can be preferable to using **this because that does ADL. + [[__gnu__::__always_inline__]] + constexpr const _Tp& + __get() const noexcept + { return *_M_objp; } + + [[no_unique_address]] _Alloc _M_alloc = _Alloc(); + pointer _M_objp; // Pointer to the owned object. + }; + + template<typename _Value> + indirect(_Value) -> indirect<_Value>; + + template<typename _Alloc, typename _Value> + indirect(allocator_arg_t, _Alloc, _Value) + -> indirect<_Value, __alloc_rebind<_Alloc, _Value>>; + + // [indirect.hash], hash support + template<typename _Tp, typename _Alloc> + requires is_default_constructible_v<hash<_Tp>> + struct hash<indirect<_Tp, _Alloc>> + { + constexpr size_t + operator()(const indirect<_Tp, _Alloc>& __t) const + noexcept(noexcept(hash<_Tp>{}(*__t))) + { + // We pick an arbitrary hash for valueless indirect objects + // which hopefully usual values of _Tp won't typically hash to. + if (__t.valueless_after_move()) + return -4444zu; + return hash<_Tp>{}(*__t); + } + }; + + template<typename _Tp, typename _Alloc> + struct __is_fast_hash<hash<indirect<_Tp, _Alloc>>> + : __is_fast_hash<hash<_Tp>> + { }; +#endif // __glibcxx_indirect + +#if __glibcxx_polymorphic // C++26 && HOSTED + template<typename _Tp, typename _Alloc = allocator<_Tp>> + class polymorphic; + + namespace pmr + { + template<typename _Tp> + using polymorphic = polymorphic<_Tp, polymorphic_allocator<_Tp>>; + } + + // [polymorphic], class template polymorphic + template<typename _Tp, typename _Alloc> + class polymorphic + { + static_assert(is_object_v<_Tp>); + static_assert(!is_array_v<_Tp>); + static_assert(!is_same_v<_Tp, in_place_t>); + static_assert(!__is_in_place_type_v<_Tp>); + static_assert(!is_const_v<_Tp> && !is_volatile_v<_Tp>); + + using _ATraits = allocator_traits<_Alloc>; + static_assert(is_same_v<_Tp, typename _ATraits::value_type>); + + // The owned object is embedded within a control block which knows the + // dynamic type and manages cloning and destroying the owned object. + struct _Obj + { + typename _ATraits::pointer _M_objp{}; // pointer to the owned object. + + // A pointer to this type, e.g. _Obj* + using pointer + = typename _ATraits::template rebind_traits<_Obj>::pointer; + + enum class _Op { _Dispose = 1, _Copy = 2, _Move = 3 }; + + constexpr virtual pointer + _M_manage(const _Alloc&, _Op, void* = nullptr) = 0; + }; + + template<typename _Up> + struct _Obj_impl : _Obj + { + using _MyTraits + = typename _ATraits::template rebind_traits<_Obj_impl>; + + using _Op = _Obj::_Op; + + union _Uninitialized { + constexpr _Uninitialized() { } + constexpr ~_Uninitialized() { } + _Up _M_objp; + }; + _Uninitialized _M_u; + + template<typename... _Args> + constexpr + _Obj_impl(typename _MyTraits::allocator_type& __a, + _Args&&... __args) + { + using _PtrTr = pointer_traits<typename _ATraits::pointer>; + _MyTraits::construct(__a, __builtin_addressof(_M_u._M_objp), + std::forward<_Args>(__args)...); + this->_M_objp = _PtrTr::pointer_to(_M_u._M_objp); + } + + constexpr virtual typename _Obj::pointer + _M_manage(const _Alloc& __a, _Op __op, void*) override + { + + switch (__op) + { + case _Op::_Move: + return _S_make_obj<_Up>(__a, std::move(_M_u._M_objp)); + case _Op::_Copy: + return _S_make_obj<_Up>(__a, + const_cast<const _Up&>(_M_u._M_objp)); + case _Op::_Dispose: + { + using _PtrTr = pointer_traits<typename _MyTraits::pointer>; + typename _MyTraits::allocator_type __a2(__a); + _MyTraits::destroy(__a2, std::__addressof(_M_u._M_objp)); + _MyTraits::deallocate(__a2, _PtrTr::pointer_to(*this), 1); + return nullptr; + } + } + __builtin_unreachable(); + } + }; + + // TODO: the standard permits a small-object optimization where the + // owned object is nested within the std::polymorphic not on the heap. + + public: + + using value_type = _Tp; + using allocator_type = _Alloc; + using pointer = typename allocator_traits<_Alloc>::pointer; + using const_pointer = typename allocator_traits<_Alloc>::const_pointer; + + constexpr explicit + polymorphic() requires is_default_constructible_v<_Alloc> + : polymorphic(in_place_type<_Tp>) + { } + + constexpr explicit + polymorphic(allocator_arg_t, const _Alloc& __a) + : polymorphic(allocator_arg, __a, in_place_type<_Tp>) + { } + + constexpr + polymorphic(const polymorphic& __other) + : polymorphic(allocator_arg, + _ATraits::select_on_container_copy_construction( + __other._M_alloc), + __other) + { } + + constexpr + polymorphic(allocator_arg_t, const _Alloc& __a, + const polymorphic& __other) + : _M_alloc(__a) + { + if (__other._M_objp) + _M_objp = __other._M_objp->_M_manage(__a, _Obj::_Op::_Copy); + else + _M_objp = nullptr; + } + + constexpr + polymorphic(polymorphic&& __other) noexcept + : _M_alloc(std::move(__other._M_alloc)), + _M_objp(std::__exchange(__other._M_objp, nullptr)) + { } + + constexpr + polymorphic(allocator_arg_t, const _Alloc& __a, polymorphic&& __other) + noexcept(_ATraits::is_always_equal::value) + : _M_alloc(__a), + _M_objp(std::__exchange(__other._M_objp, nullptr)) + { + if constexpr (!_ATraits::is_always_equal::value) + if (_M_objp && _M_alloc != __other._M_alloc) + { + // _M_alloc cannot free _M_objp, give it back to __other. + __other._M_objp = std::__exchange(_M_objp, nullptr); + // And create a new object that can be freed by _M_alloc. + _M_objp = __other._M_objp->_M_manage(__a, _Obj::_Op::_Move); + } + } + + template<typename _Up = _Tp, typename _UUp = remove_cvref_t<_Up>> + requires (!is_same_v<_UUp, polymorphic>) + && (!__is_in_place_type_v<_UUp>) + && derived_from<_UUp, _Tp> + && is_constructible_v<_UUp, _Up> + && is_copy_constructible_v<_UUp> + && is_default_constructible_v<_Alloc> + constexpr explicit + polymorphic(_Up&& __u) + : _M_objp(_M_make_obj<_UUp>(std::forward<_Up>(__u))) + { } + + template<typename _Up = _Tp, typename _UUp = remove_cvref_t<_Up>> + requires (!is_same_v<_UUp, polymorphic>) + && (!__is_in_place_type_v<_UUp>) + && derived_from<_UUp, _Tp> + && is_constructible_v<_UUp, _Up> + && is_copy_constructible_v<_UUp> + constexpr explicit + polymorphic(allocator_arg_t, const _Alloc& __a, _Up&& __u) + : _M_alloc(__a), _M_objp(_M_make_obj<_UUp>(std::forward<_Up>(__u))) + { } + + template<typename _Up, typename... _Ts> + requires is_same_v<remove_cvref_t<_Up>, _Up> + && derived_from<_Up, _Tp> + && is_constructible_v<_Up, _Ts...> + && is_copy_constructible_v<_Up> + && is_default_constructible_v<_Alloc> + constexpr explicit + polymorphic(in_place_type_t<_Up> __t, _Ts&&... __ts) + : _M_objp(_M_make_obj<_Up>(std::forward<_Ts>(__ts)...)) + { } + + template<typename _Up, typename... _Ts> + requires is_same_v<remove_cvref_t<_Up>, _Up> + && derived_from<_Up, _Tp> + && is_constructible_v<_Up, _Ts...> + && is_copy_constructible_v<_Up> + constexpr explicit + polymorphic(allocator_arg_t, const _Alloc& __a, + in_place_type_t<_Up>, _Ts&&... __ts) + : _M_alloc(__a), + _M_objp(_M_make_obj<_Up>(std::forward<_Ts>(__ts)...)) + { } + + template<typename _Up, typename _Ip, typename... _Us> + requires is_same_v<remove_cvref_t<_Up>, _Up> + && derived_from<_Up, _Tp> + && is_constructible_v<_Up, initializer_list<_Ip>&, _Us...> + && is_copy_constructible_v<_Up> + && is_default_constructible_v<_Alloc> + constexpr explicit + polymorphic(in_place_type_t<_Up>, initializer_list<_Ip> __il, + _Us&&... __us) + : _M_objp(_M_make_obj<_Up>(__il, std::forward<_Us>(__us)...)) + { } + + template<typename _Up, typename _Ip, typename... _Us> + requires is_same_v<remove_cvref_t<_Up>, _Up> + && derived_from<_Up, _Tp> + && is_constructible_v<_Up, initializer_list<_Ip>&, _Us...> + && is_copy_constructible_v<_Up> + constexpr explicit + polymorphic(allocator_arg_t, const _Alloc& __a, + in_place_type_t<_Up>, initializer_list<_Ip> __il, + _Us&&... __us) + : _M_alloc(__a), + _M_objp(_M_make_obj<_Up>(__il, std::forward<_Us>(__us)...)) + { } + + constexpr ~polymorphic() + { + static_assert(sizeof(_Tp) != 0, "must be a complete type"); + _M_reset(nullptr); + } + + constexpr polymorphic& + operator=(const polymorphic& __other) + { + static_assert(sizeof(_Tp) != 0, "must be a complete type"); + + if (__builtin_addressof(__other) == this) [[unlikely]] + return *this; + + constexpr bool __pocca + = _ATraits::propagate_on_container_copy_assignment::value; + + typename _Obj::pointer __ptr = nullptr; + if (__other._M_objp) + { + auto& __a = __pocca ? __other._M_alloc : _M_alloc; + __ptr = __other._M_objp->_M_manage(__a, _Obj::_Op::_Copy); + } + + _M_reset(__ptr); + + if constexpr (__pocca) + _M_alloc = __other._M_alloc; + + return *this; + } + + constexpr polymorphic& + operator=(polymorphic&& __other) + noexcept(_ATraits::propagate_on_container_move_assignment::value + || _ATraits::is_always_equal::value) + { + if (__builtin_addressof(__other) == this) [[unlikely]] + return *this; + + constexpr bool __pocma + = _ATraits::propagate_on_container_move_assignment::value; + + typename _Obj::pointer __ptr = nullptr; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4251. Move assignment for indirect unnecessarily requires copy construction + if constexpr (_ATraits::is_always_equal::value || __pocma) + __ptr = std::__exchange(__other._M_objp, nullptr); + else if (_M_alloc == __other._M_alloc) + __ptr = std::__exchange(__other._M_objp, nullptr); + else if (__other._M_objp) + { + static_assert(sizeof(_Tp) != 0, "must be a complete type"); + __ptr = __other._M_objp->_M_manage(_M_alloc, _Obj::_Op::_Move); + } + + _M_reset(__ptr); + + if constexpr (__pocma) + _M_alloc = std::move(__other._M_alloc); + + return *this; + } + + constexpr const _Tp& + operator*() const noexcept + { + __glibcxx_assert(_M_objp != nullptr); + return *_M_objp->_M_objp; + } + + constexpr _Tp& + operator*() noexcept + { + __glibcxx_assert(_M_objp != nullptr); + return *_M_objp->_M_objp; + } + + constexpr const_pointer + operator->() const noexcept + { + __glibcxx_assert(_M_objp != nullptr); + return _M_objp ? _M_objp->_M_objp : const_pointer{}; + } + + constexpr pointer + operator->() noexcept + { + __glibcxx_assert(_M_objp != nullptr); + return _M_objp ? _M_objp->_M_objp : pointer{}; + } + + constexpr bool + valueless_after_move() const noexcept { return _M_objp == nullptr; } + + constexpr allocator_type + get_allocator() const noexcept { return _M_alloc; } + + constexpr void + swap(polymorphic& __other) + noexcept(_ATraits::propagate_on_container_swap::value + || _ATraits::is_always_equal::value) + { + using std::swap; + swap(_M_objp, __other._M_objp); + if constexpr (_ATraits::propagate_on_container_swap::value) + swap(_M_alloc, __other._M_alloc); + else if constexpr (!_ATraits::is_always_equal::value) + __glibcxx_assert(_M_alloc == __other._M_alloc); + } + + friend constexpr void + swap(polymorphic& __lhs, polymorphic& __rhs) + noexcept(_ATraits::propagate_on_container_swap::value + || _ATraits::is_always_equal::value) + { __lhs.swap(__rhs); } + + private: + template<typename _Up, typename... _Args> + static constexpr typename _Obj::pointer + _S_make_obj(const _Alloc& __a, _Args&&... __args) + { + __alloc_rebind<_Alloc, _Obj_impl<_Up>> __objalloc(__a); + _Scoped_allocation __sa(__objalloc, in_place, __objalloc, + std::forward<_Args>(__args)...); + auto __obj = __sa.release(); + // FIXME: We need to downcast from _Obj_impl<U>* to _Obj* but the + // the pointer_traits usage breaks in constexpr. PR c++/110714 + if constexpr (is_pointer_v<typename _Obj::pointer>) + return __obj; + else + return pointer_traits<typename _Obj::pointer>::pointer_to(*__obj); + } + + template<typename _Up, typename... _Args> + constexpr typename _Obj::pointer + _M_make_obj(_Args&&... __args) const + { return _S_make_obj<_Up>(_M_alloc, std::forward<_Args>(__args)...); } + + constexpr void + _M_reset(typename _Obj::pointer __ptr) noexcept + { + if (_M_objp) + _M_objp->_M_manage(_M_alloc, _Obj::_Op::_Dispose); + _M_objp = __ptr; + } + + [[no_unique_address]] _Alloc _M_alloc = _Alloc(); + typename _Obj::pointer _M_objp; + }; +#endif // __glibcxx_polymorphic + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +#endif // C++26 __glibcxx_indirect || __glibcxx_polymorphic + +#endif // _GLIBCXX_INDIRECT_H diff --git a/libstdc++-v3/include/bits/intcmp.h b/libstdc++-v3/include/bits/intcmp.h new file mode 100644 index 0000000..bb9c7f2 --- /dev/null +++ b/libstdc++-v3/include/bits/intcmp.h @@ -0,0 +1,120 @@ +// Integer comparison functions -*- C++ -*- + +// Copyright (C) 2020-2025 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// <http://www.gnu.org/licenses/>. + +/** @file bits/intcmp.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{utility} + */ + +#ifndef _GLIBCXX_INTCMP_H +#define _GLIBCXX_INTCMP_H 1 + +#ifdef _GLIBCXX_SYSHDR +#pragma GCC system_header +#endif + +#include <bits/version.h> + +#ifdef __glibcxx_integer_comparison_functions // C++ >= 20 + +#include <type_traits> +#include <ext/numeric_traits.h> // __int_traits + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template<typename _Tp, typename _Up> + constexpr bool + cmp_equal(_Tp __t, _Up __u) noexcept + { + static_assert(__is_signed_or_unsigned_integer<_Tp>::value); + static_assert(__is_signed_or_unsigned_integer<_Up>::value); + + if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) + return __t == __u; + else if constexpr (is_signed_v<_Tp>) + return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u; + else + return __u >= 0 && __t == make_unsigned_t<_Up>(__u); + } + + template<typename _Tp, typename _Up> + constexpr bool + cmp_not_equal(_Tp __t, _Up __u) noexcept + { return !std::cmp_equal(__t, __u); } + + template<typename _Tp, typename _Up> + constexpr bool + cmp_less(_Tp __t, _Up __u) noexcept + { + static_assert(__is_signed_or_unsigned_integer<_Tp>::value); + static_assert(__is_signed_or_unsigned_integer<_Up>::value); + + if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) + return __t < __u; + else if constexpr (is_signed_v<_Tp>) + return __t < 0 || make_unsigned_t<_Tp>(__t) < __u; + else + return __u >= 0 && __t < make_unsigned_t<_Up>(__u); + } + + template<typename _Tp, typename _Up> + constexpr bool + cmp_greater(_Tp __t, _Up __u) noexcept + { return std::cmp_less(__u, __t); } + + template<typename _Tp, typename _Up> + constexpr bool + cmp_less_equal(_Tp __t, _Up __u) noexcept + { return !std::cmp_less(__u, __t); } + + template<typename _Tp, typename _Up> + constexpr bool + cmp_greater_equal(_Tp __t, _Up __u) noexcept + { return !std::cmp_less(__t, __u); } + + template<typename _Res, typename _Tp> + constexpr bool + in_range(_Tp __t) noexcept + { + static_assert(__is_signed_or_unsigned_integer<_Res>::value); + static_assert(__is_signed_or_unsigned_integer<_Tp>::value); + using __gnu_cxx::__int_traits; + + if constexpr (is_signed_v<_Tp> == is_signed_v<_Res>) + return __int_traits<_Res>::__min <= __t + && __t <= __int_traits<_Res>::__max; + else if constexpr (is_signed_v<_Tp>) + return __t >= 0 + && make_unsigned_t<_Tp>(__t) <= __int_traits<_Res>::__max; + else + return __t <= make_unsigned_t<_Res>(__int_traits<_Res>::__max); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // __glibcxx_integer_comparison_functions +#endif // _GLIBCXX_INTCMP_H diff --git a/libstdc++-v3/include/bits/ios_base.h b/libstdc++-v3/include/bits/ios_base.h index b94b2cd..adc2982 100644 --- a/libstdc++-v3/include/bits/ios_base.h +++ b/libstdc++-v3/include/bits/ios_base.h @@ -56,7 +56,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // as permitted (but not required) in the standard, in order to provide // better type safety in iostream calls. A side effect is that in C++98 // expressions involving them are not compile-time constants. - enum _Ios_Fmtflags + enum __attribute__((__flag_enum__)) _Ios_Fmtflags { _S_boolalpha = 1L << 0, _S_dec = 1L << 1, @@ -76,9 +76,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _S_adjustfield = _S_left | _S_right | _S_internal, _S_basefield = _S_dec | _S_oct | _S_hex, _S_floatfield = _S_scientific | _S_fixed, - _S_ios_fmtflags_end = 1L << 16, - _S_ios_fmtflags_max = __INT_MAX__, - _S_ios_fmtflags_min = ~__INT_MAX__ + _S_ios_fmtflags_end __attribute__((__unused__)) = 1L << 16, + _S_ios_fmtflags_max __attribute__((__unused__)) = __INT_MAX__, + _S_ios_fmtflags_min __attribute__((__unused__)) = ~__INT_MAX__ }; _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR @@ -176,15 +176,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __a = __a ^ __b; } - enum _Ios_Iostate + enum __attribute__((__flag_enum__)) _Ios_Iostate { _S_goodbit = 0, _S_badbit = 1L << 0, _S_eofbit = 1L << 1, _S_failbit = 1L << 2, - _S_ios_iostate_end = 1L << 16, - _S_ios_iostate_max = __INT_MAX__, - _S_ios_iostate_min = ~__INT_MAX__ + _S_ios_iostate_end __attribute__((__unused__)) = 1L << 16, + _S_ios_iostate_max __attribute__((__unused__)) = __INT_MAX__, + _S_ios_iostate_min __attribute__((__unused__)) = ~__INT_MAX__ }; _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR @@ -228,7 +228,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _S_beg = 0, _S_cur = _GLIBCXX_STDIO_SEEK_CUR, _S_end = _GLIBCXX_STDIO_SEEK_END, - _S_ios_seekdir_end = 1L << 16 + _S_ios_seekdir_end __attribute__((__unused__)) = 1L << 16 }; #if __cplusplus >= 201103L diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h index 3b73ff9..40ac808 100644 --- a/libstdc++-v3/include/bits/iterator_concepts.h +++ b/libstdc++-v3/include/bits/iterator_concepts.h @@ -39,9 +39,6 @@ #include <bits/ptr_traits.h> // to_address #include <bits/ranges_cmp.h> // identity, ranges::less -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" // __int128 - namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -148,7 +145,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; template<typename _Tp> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (__adl_imove<_Tp>) @@ -214,17 +211,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION = make_signed_t<decltype(std::declval<_Tp>() - std::declval<_Tp>())>; }; -#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ - // __int128 is incrementable even if !integral<__int128> - template<> - struct incrementable_traits<__int128> - { using difference_type = __int128; }; - - template<> - struct incrementable_traits<unsigned __int128> - { using difference_type = __int128; }; -#endif - namespace __detail { // An iterator such that iterator_traits<_Iter> names a specialization @@ -611,24 +597,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class __max_diff_type; class __max_size_type; - __extension__ - template<typename _Tp> - concept __is_signed_int128 -#if __SIZEOF_INT128__ - = same_as<_Tp, __int128>; -#else - = false; -#endif - - __extension__ - template<typename _Tp> - concept __is_unsigned_int128 -#if __SIZEOF_INT128__ - = same_as<_Tp, unsigned __int128>; -#else - = false; -#endif - template<typename _Tp> concept __cv_bool = same_as<const volatile _Tp, const volatile bool>; @@ -636,16 +604,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION concept __integral_nonbool = integral<_Tp> && !__cv_bool<_Tp>; template<typename _Tp> - concept __is_int128 = __is_signed_int128<_Tp> || __is_unsigned_int128<_Tp>; - - template<typename _Tp> concept __is_integer_like = __integral_nonbool<_Tp> - || __is_int128<_Tp> || same_as<_Tp, __max_diff_type> || same_as<_Tp, __max_size_type>; template<typename _Tp> concept __is_signed_integer_like = signed_integral<_Tp> - || __is_signed_int128<_Tp> || same_as<_Tp, __max_diff_type>; } // namespace ranges::__detail @@ -918,7 +881,7 @@ namespace ranges { private: template<typename _Tp, typename _Up> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (__adl_iswap<_Tp, _Up>) @@ -1022,19 +985,10 @@ namespace ranges { using std::__detail::__class_or_enum; - struct _Decay_copy final - { - template<typename _Tp> - constexpr decay_t<_Tp> - operator()(_Tp&& __t) const - noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>) - { return std::forward<_Tp>(__t); } - } inline constexpr __decay_copy{}; - template<typename _Tp> concept __member_begin = requires(_Tp& __t) { - { __decay_copy(__t.begin()) } -> input_or_output_iterator; + { _GLIBCXX_AUTO_CAST(__t.begin()) } -> input_or_output_iterator; }; // Poison pill so that unqualified lookup doesn't find std::begin. @@ -1044,7 +998,7 @@ namespace ranges concept __adl_begin = __class_or_enum<remove_reference_t<_Tp>> && requires(_Tp& __t) { - { __decay_copy(begin(__t)) } -> input_or_output_iterator; + { _GLIBCXX_AUTO_CAST(begin(__t)) } -> input_or_output_iterator; }; // Simplified version of std::ranges::begin that only supports lvalues, @@ -1075,6 +1029,5 @@ namespace ranges #endif // C++20 library concepts _GLIBCXX_END_NAMESPACE_VERSION } // namespace std -#pragma GCC diagnostic pop #endif // C++20 #endif // _ITERATOR_CONCEPTS_H diff --git a/libstdc++-v3/include/bits/max_size_type.h b/libstdc++-v3/include/bits/max_size_type.h index 5bec0b5..537acee 100644 --- a/libstdc++-v3/include/bits/max_size_type.h +++ b/libstdc++-v3/include/bits/max_size_type.h @@ -36,16 +36,16 @@ #if __cplusplus > 201703L && __cpp_lib_concepts #include <ext/numeric_traits.h> +#include <bit> // __bit_width #include <numbers> +#include <limits> // __glibcxx_integral_traps // This header implements unsigned and signed integer-class types (as per // [iterator.concept.winc]) that are one bit wider than the widest supported // integer type. // -// The set of integer types we consider includes __int128 and unsigned __int128 -// (when they exist), even though they are really integer types only in GNU -// mode. This is to obtain a consistent ABI for these integer-class types -// across strict mode and GNU mode. +// The set of integer types we consider includes the extended integer types +// __int128 and unsigned __int128 (when they exist). namespace std _GLIBCXX_VISIBILITY(default) { @@ -63,7 +63,7 @@ namespace ranges public: __max_size_type() = default; - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> constexpr __max_size_type(_Tp __i) noexcept : _M_val(__i), _M_msb(__i < 0) @@ -72,7 +72,7 @@ namespace ranges constexpr explicit __max_size_type(const __max_diff_type& __d) noexcept; - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> constexpr explicit operator _Tp() const noexcept { return _M_val; } @@ -258,52 +258,52 @@ namespace ranges return *this; } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator+=(_Tp& __a, const __max_size_type& __b) noexcept { return (__a = static_cast<_Tp>(__a + __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator-=(_Tp& __a, const __max_size_type& __b) noexcept { return (__a = static_cast<_Tp>(__a - __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator*=(_Tp& __a, const __max_size_type& __b) noexcept { return (__a = static_cast<_Tp>(__a * __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator/=(_Tp& __a, const __max_size_type& __b) noexcept { return (__a = static_cast<_Tp>(__a / __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator%=(_Tp& __a, const __max_size_type& __b) noexcept { return (__a = static_cast<_Tp>(__a % __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator&=(_Tp& __a, const __max_size_type& __b) noexcept { return (__a = static_cast<_Tp>(__a & __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator|=(_Tp& __a, const __max_size_type& __b) noexcept { return (__a = static_cast<_Tp>(__a | __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator^=(_Tp& __a, const __max_size_type& __b) noexcept { return (__a = static_cast<_Tp>(__a ^ __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator<<=(_Tp& __a, const __max_size_type& __b) noexcept { return (__a = static_cast<_Tp>(__a << __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator>>=(_Tp& __a, const __max_size_type& __b) noexcept { return (__a = static_cast<_Tp>(__a >> __b)); } @@ -425,10 +425,11 @@ namespace ranges using __rep = unsigned long long; #endif static constexpr size_t _S_rep_bits = sizeof(__rep) * __CHAR_BIT__; - private: + __rep _M_val = 0; unsigned _M_msb:1 = 0; + private: constexpr explicit __max_size_type(__rep __val, int __msb) noexcept : _M_val(__val), _M_msb(__msb) @@ -444,7 +445,7 @@ namespace ranges public: __max_diff_type() = default; - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> constexpr __max_diff_type(_Tp __i) noexcept : _M_rep(__i) @@ -455,7 +456,7 @@ namespace ranges : _M_rep(__d) { } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> constexpr explicit operator _Tp() const noexcept { return static_cast<_Tp>(_M_rep); } @@ -588,52 +589,52 @@ namespace ranges return *this; } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator+=(_Tp& __a, const __max_diff_type& __b) noexcept { return (__a = static_cast<_Tp>(__a + __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator-=(_Tp& __a, const __max_diff_type& __b) noexcept { return (__a = static_cast<_Tp>(__a - __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator*=(_Tp& __a, const __max_diff_type& __b) noexcept { return (__a = static_cast<_Tp>(__a * __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator/=(_Tp& __a, const __max_diff_type& __b) noexcept { return (__a = static_cast<_Tp>(__a / __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator%=(_Tp& __a, const __max_diff_type& __b) noexcept { return (__a = static_cast<_Tp>(__a % __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator&=(_Tp& __a, const __max_diff_type& __b) noexcept { return (__a = static_cast<_Tp>(__a & __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator|=(_Tp& __a, const __max_diff_type& __b) noexcept { return (__a = static_cast<_Tp>(__a | __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator^=(_Tp& __a, const __max_diff_type& __b) noexcept { return (__a = static_cast<_Tp>(__a ^ __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator<<=(_Tp& __a, const __max_diff_type& __b) noexcept { return (__a = static_cast<_Tp>(__a << __b)); } - template<typename _Tp> requires integral<_Tp> || __is_int128<_Tp> + template<typename _Tp> requires integral<_Tp> friend constexpr _Tp& operator>>=(_Tp& __a, const __max_diff_type& __b) noexcept { return (__a = static_cast<_Tp>(__a >> __b)); } @@ -752,7 +753,6 @@ namespace ranges { return !(__l < __r); } #endif - private: __max_size_type _M_rep = 0; friend class __max_size_type; @@ -774,10 +774,27 @@ namespace ranges static constexpr bool is_signed = false; static constexpr bool is_integer = true; static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = true; + static constexpr bool traps = __glibcxx_integral_traps; + static constexpr int radix = 2; static constexpr int digits = __gnu_cxx::__int_traits<_Sp::__rep>::__digits + 1; static constexpr int digits10 = static_cast<int>(digits * numbers::ln2 / numbers::ln10); + static constexpr int max_digits10 = 0; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool is_iec559 = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr bool has_denorm_loss = false; + static constexpr bool tinyness_before = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr float_round_style round_style = round_toward_zero; static constexpr _Sp min() noexcept @@ -790,6 +807,30 @@ namespace ranges static constexpr _Sp lowest() noexcept { return min(); } + + static constexpr _Sp + denorm_min() noexcept + { return 0; } + + static constexpr _Sp + epsilon() noexcept + { return 0; } + + static constexpr _Sp + round_error() noexcept + { return 0; } + + static constexpr _Sp + infinity() noexcept + { return 0; } + + static constexpr _Sp + quiet_NaN() noexcept + { return 0; } + + static constexpr _Sp + signaling_NaN() noexcept + { return 0; } }; template<> @@ -801,9 +842,26 @@ namespace ranges static constexpr bool is_signed = true; static constexpr bool is_integer = true; static constexpr bool is_exact = true; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr bool traps = __glibcxx_integral_traps; + static constexpr int radix = 2; static constexpr int digits = numeric_limits<_Sp>::digits - 1; static constexpr int digits10 = static_cast<int>(digits * numbers::ln2 / numbers::ln10); + static constexpr int max_digits10 = 0; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + static constexpr bool is_iec559 = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr bool has_denorm_loss = false; + static constexpr bool tinyness_before = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr float_round_style round_style = round_toward_zero; static constexpr _Dp min() noexcept @@ -816,8 +874,42 @@ namespace ranges static constexpr _Dp lowest() noexcept { return min(); } + + static constexpr _Dp + denorm_min() noexcept + { return 0; } + + static constexpr _Dp + epsilon() noexcept + { return 0; } + + static constexpr _Dp + round_error() noexcept + { return 0; } + + static constexpr _Dp + infinity() noexcept + { return 0; } + + static constexpr _Dp + quiet_NaN() noexcept + { return 0; } + + static constexpr _Dp + signaling_NaN() noexcept + { return 0; } }; + template<> + inline constexpr int + __bit_width(ranges::__detail::__max_size_type __x) noexcept + { + if (__x._M_msb) + return numeric_limits<ranges::__detail::__max_size_type>::digits; + else + return std::__bit_width(__x._M_val); + } + _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/include/bits/mofunc_impl.h b/libstdc++-v3/include/bits/mofunc_impl.h index 318a55e..468e685 100644 --- a/libstdc++-v3/include/bits/mofunc_impl.h +++ b/libstdc++-v3/include/bits/mofunc_impl.h @@ -62,8 +62,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Res, typename... _ArgTypes, bool _Noex> class move_only_function<_Res(_ArgTypes...) _GLIBCXX_MOF_CV _GLIBCXX_MOF_REF noexcept(_Noex)> - : _Mofunc_base + : __polyfunc::_Mo_base { + static_assert( + (std::__is_complete_or_unbounded(__type_identity<_ArgTypes>()) && ...), + "each parameter type must be a complete class"); + + using _Base = __polyfunc::_Mo_base; + using _Invoker = __polyfunc::_Invoker<_Noex, _Res, _ArgTypes...>; + using _Signature = _Invoker::_Signature; + template<typename _Tp> using __callable = __conditional_t<_Noex, @@ -87,7 +95,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Moves the target object, leaving the source empty. move_only_function(move_only_function&& __x) noexcept - : _Mofunc_base(static_cast<_Mofunc_base&&>(__x)), + : _Base(static_cast<_Base&&>(__x)), _M_invoke(std::__exchange(__x._M_invoke, nullptr)) { } @@ -97,15 +105,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION && (!__is_in_place_type_v<_Vt>) && __is_callable_from<_Vt> move_only_function(_Fn&& __f) noexcept(_S_nothrow_init<_Vt, _Fn>()) { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4255. move_only_function constructor should recognize empty + // copyable_functions if constexpr (is_function_v<remove_pointer_t<_Vt>> || is_member_pointer_v<_Vt> - || __is_move_only_function_v<_Vt>) + || __is_polymorphic_function_v<_Vt>) { if (__f == nullptr) return; } - _M_init<_Vt>(std::forward<_Fn>(__f)); - _M_invoke = &_S_invoke<_Vt>; + + if constexpr (__is_polymorphic_function_v<_Vt> + && __polyfunc::__is_invoker_convertible<_Vt, move_only_function>()) + { + // Handle cases where _Fn is const reference to copyable_function, + // by firstly creating temporary and moving from it. + _Vt __tmp(std::forward<_Fn>(__f)); + _M_move(__polyfunc::__base_of(__tmp)); + _M_invoke = std::__exchange(__polyfunc::__invoker_of(__tmp), nullptr); + } + else + { + _M_init<_Vt>(std::forward<_Fn>(__f)); + _M_invoke = _Invoker::template _S_storage<_Vt _GLIBCXX_MOF_INV_QUALS>(); + } } /// Stores a target object initialized from the arguments. @@ -115,7 +139,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION explicit move_only_function(in_place_type_t<_Tp>, _Args&&... __args) noexcept(_S_nothrow_init<_Tp, _Args...>()) - : _M_invoke(&_S_invoke<_Tp>) + : _M_invoke(_Invoker::template _S_storage<_Tp _GLIBCXX_MOF_INV_QUALS>()) { static_assert(is_same_v<decay_t<_Tp>, _Tp>); _M_init<_Tp>(std::forward<_Args>(__args)...); @@ -129,7 +153,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION move_only_function(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args) noexcept(_S_nothrow_init<_Tp, initializer_list<_Up>&, _Args...>()) - : _M_invoke(&_S_invoke<_Tp>) + : _M_invoke(_Invoker::template _S_storage<_Tp _GLIBCXX_MOF_INV_QUALS>()) { static_assert(is_same_v<decay_t<_Tp>, _Tp>); _M_init<_Tp>(__il, std::forward<_Args>(__args)...); @@ -139,8 +163,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION move_only_function& operator=(move_only_function&& __x) noexcept { - _Mofunc_base::operator=(static_cast<_Mofunc_base&&>(__x)); - _M_invoke = std::__exchange(__x._M_invoke, nullptr); + // Standard requires support of self assigment, by specifying it as + // copy and swap. + if (this != std::addressof(__x)) [[likely]] + { + _Base::operator=(static_cast<_Base&&>(__x)); + _M_invoke = std::__exchange(__x._M_invoke, nullptr); + } return *this; } @@ -148,7 +177,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION move_only_function& operator=(nullptr_t) noexcept { - _Mofunc_base::operator=(nullptr); + _M_reset(); _M_invoke = nullptr; return *this; } @@ -167,7 +196,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ~move_only_function() = default; /// True if a target object is present, false otherwise. - explicit operator bool() const noexcept { return _M_invoke != nullptr; } + explicit operator bool() const noexcept + { return _M_invoke != nullptr; } /** Invoke the target object. * @@ -181,14 +211,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator()(_ArgTypes... __args) _GLIBCXX_MOF_CV_REF noexcept(_Noex) { __glibcxx_assert(*this != nullptr); - return _M_invoke(this, std::forward<_ArgTypes>(__args)...); + return _M_invoke(this->_M_storage, std::forward<_ArgTypes>(__args)...); } /// Exchange the target objects (if any). void swap(move_only_function& __x) noexcept { - _Mofunc_base::swap(__x); + _Base::swap(__x); std::swap(_M_invoke, __x._M_invoke); } @@ -203,25 +233,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __x._M_invoke == nullptr; } private: - template<typename _Tp> - using __param_t = __conditional_t<is_scalar_v<_Tp>, _Tp, _Tp&&>; + typename _Invoker::__storage_func_t _M_invoke = nullptr; - using _Invoker = _Res (*)(_Mofunc_base _GLIBCXX_MOF_CV*, - __param_t<_ArgTypes>...) noexcept(_Noex); + template<typename _Func> + friend auto& + __polyfunc::__invoker_of(_Func&) noexcept; - template<typename _Tp> - static _Res - _S_invoke(_Mofunc_base _GLIBCXX_MOF_CV* __self, - __param_t<_ArgTypes>... __args) noexcept(_Noex) - { - using _TpCv = _Tp _GLIBCXX_MOF_CV; - using _TpInv = _Tp _GLIBCXX_MOF_INV_QUALS; - return std::__invoke_r<_Res>( - std::forward<_TpInv>(*_S_access<_TpCv>(__self)), - std::forward<__param_t<_ArgTypes>>(__args)...); - } + template<typename _Func> + friend auto& + __polyfunc::__base_of(_Func&) noexcept; - _Invoker _M_invoke = nullptr; + template<typename _Dst, typename _Src> + friend consteval bool + __polyfunc::__is_invoker_convertible() noexcept; }; #undef _GLIBCXX_MOF_CV_REF diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h index 085ca07..8c4f461 100644 --- a/libstdc++-v3/include/bits/move.h +++ b/libstdc++-v3/include/bits/move.h @@ -89,7 +89,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return static_cast<_Tp&&>(__t); } -#if __glibcxx_forward_like // C++ >= 23 template<typename _Tp, typename _Up> struct __like_impl; // _Tp must be a reference and _Up an lvalue reference @@ -112,6 +111,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, typename _Up> using __like_t = typename __like_impl<_Tp&&, _Up&>::type; +#if __glibcxx_forward_like // C++ >= 23 /** @brief Forward with the cv-qualifiers and value category of another type. * @tparam _Tp An lvalue reference or rvalue reference. * @tparam _Up An lvalue reference type deduced from the function argument. @@ -215,14 +215,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @return Nothing. */ template<typename _Tp> - _GLIBCXX20_CONSTEXPR - inline -#if __cplusplus >= 201103L - typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>, - is_move_constructible<_Tp>, - is_move_assignable<_Tp>>::value>::type +#if __glibcxx_concepts // >= C++20 + requires (! __is_tuple_like<_Tp>::value) + && is_move_constructible_v<_Tp> + && is_move_assignable_v<_Tp> + constexpr void +#elif __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR inline + __enable_if_t<__and_<__not_<__is_tuple_like<_Tp>>, + is_move_constructible<_Tp>, + is_move_assignable<_Tp>>::value> #else - void + inline void #endif swap(_Tp& __a, _Tp& __b) _GLIBCXX_NOEXCEPT_IF(__and_<is_nothrow_move_constructible<_Tp>, @@ -241,12 +245,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // DR 809. std::swap should be overloaded for array types. /// Swap the contents of two arrays. template<typename _Tp, size_t _Nm> - _GLIBCXX20_CONSTEXPR - inline -#if __cplusplus >= 201103L - typename enable_if<__is_swappable<_Tp>::value>::type +#if __glibcxx_concepts // >= C++20 + requires is_swappable_v<_Tp> + constexpr void +#elif __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR inline + __enable_if_t<__is_swappable<_Tp>::value> #else - void + inline void #endif swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Tp>::value) diff --git a/libstdc++-v3/include/bits/move_only_function.h b/libstdc++-v3/include/bits/move_only_function.h deleted file mode 100644 index 42b33d0..0000000 --- a/libstdc++-v3/include/bits/move_only_function.h +++ /dev/null @@ -1,218 +0,0 @@ -// Implementation of std::move_only_function -*- C++ -*- - -// Copyright The GNU Toolchain Authors. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// <http://www.gnu.org/licenses/>. - -/** @file include/bits/move_only_function.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{functional} - */ - -#ifndef _GLIBCXX_MOVE_ONLY_FUNCTION_H -#define _GLIBCXX_MOVE_ONLY_FUNCTION_H 1 - -#ifdef _GLIBCXX_SYSHDR -#pragma GCC system_header -#endif - -#include <bits/version.h> - -#ifdef __glibcxx_move_only_function // C++ >= 23 && HOSTED - -#include <bits/invoke.h> -#include <bits/utility.h> - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - template<typename... _Signature> - class move_only_function; // not defined - - /// @cond undocumented - class _Mofunc_base - { - protected: - _Mofunc_base() noexcept - : _M_manage(_S_empty) - { } - - _Mofunc_base(_Mofunc_base&& __x) noexcept - { - _M_manage = std::__exchange(__x._M_manage, _S_empty); - _M_manage(_M_storage, &__x._M_storage); - } - - template<typename _Tp, typename... _Args> - static constexpr bool - _S_nothrow_init() noexcept - { - if constexpr (__stored_locally<_Tp>) - return is_nothrow_constructible_v<_Tp, _Args...>; - return false; - } - - template<typename _Tp, typename... _Args> - void - _M_init(_Args&&... __args) noexcept(_S_nothrow_init<_Tp, _Args...>()) - { - if constexpr (__stored_locally<_Tp>) - ::new (_M_storage._M_addr()) _Tp(std::forward<_Args>(__args)...); - else - _M_storage._M_p = new _Tp(std::forward<_Args>(__args)...); - - _M_manage = &_S_manage<_Tp>; - } - - _Mofunc_base& - operator=(_Mofunc_base&& __x) noexcept - { - _M_manage(_M_storage, nullptr); - _M_manage = std::__exchange(__x._M_manage, _S_empty); - _M_manage(_M_storage, &__x._M_storage); - return *this; - } - - _Mofunc_base& - operator=(nullptr_t) noexcept - { - _M_manage(_M_storage, nullptr); - _M_manage = _S_empty; - return *this; - } - - ~_Mofunc_base() { _M_manage(_M_storage, nullptr); } - - void - swap(_Mofunc_base& __x) noexcept - { - // Order of operations here is more efficient if __x is empty. - _Storage __s; - __x._M_manage(__s, &__x._M_storage); - _M_manage(__x._M_storage, &_M_storage); - __x._M_manage(_M_storage, &__s); - std::swap(_M_manage, __x._M_manage); - } - - template<typename _Tp, typename _Self> - static _Tp* - _S_access(_Self* __self) noexcept - { - if constexpr (__stored_locally<remove_const_t<_Tp>>) - return static_cast<_Tp*>(__self->_M_storage._M_addr()); - else - return static_cast<_Tp*>(__self->_M_storage._M_p); - } - - private: - struct _Storage - { - void* _M_addr() noexcept { return &_M_bytes[0]; } - const void* _M_addr() const noexcept { return &_M_bytes[0]; } - - // We want to have enough space to store a simple delegate type. - struct _Delegate { void (_Storage::*__pfm)(); _Storage* __obj; }; - union { - void* _M_p; - alignas(_Delegate) alignas(void(*)()) - unsigned char _M_bytes[sizeof(_Delegate)]; - }; - }; - - template<typename _Tp> - static constexpr bool __stored_locally - = sizeof(_Tp) <= sizeof(_Storage) && alignof(_Tp) <= alignof(_Storage) - && is_nothrow_move_constructible_v<_Tp>; - - // A function that either destroys the target object stored in __target, - // or moves the target object from *__src to __target. - using _Manager = void (*)(_Storage& __target, _Storage* __src) noexcept; - - // The no-op manager function for objects with no target. - static void _S_empty(_Storage&, _Storage*) noexcept { } - - // The real manager function for a target object of type _Tp. - template<typename _Tp> - static void - _S_manage(_Storage& __target, _Storage* __src) noexcept - { - if constexpr (__stored_locally<_Tp>) - { - if (__src) - { - _Tp* __rval = static_cast<_Tp*>(__src->_M_addr()); - ::new (__target._M_addr()) _Tp(std::move(*__rval)); - __rval->~_Tp(); - } - else - static_cast<_Tp*>(__target._M_addr())->~_Tp(); - } - else - { - if (__src) - __target._M_p = __src->_M_p; - else - delete static_cast<_Tp*>(__target._M_p); - } - } - - _Storage _M_storage; - _Manager _M_manage; - }; - - template<typename _Tp> - inline constexpr bool __is_move_only_function_v = false; - template<typename _Tp> - constexpr bool __is_move_only_function_v<move_only_function<_Tp>> = true; - /// @endcond - - namespace __detail::__variant - { - template<typename> struct _Never_valueless_alt; // see <variant> - - // Provide the strong exception-safety guarantee when emplacing a - // move_only_function into a variant. - template<typename... _Signature> - struct _Never_valueless_alt<std::move_only_function<_Signature...>> - : true_type - { }; - } // namespace __detail::__variant - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#include "mofunc_impl.h" -#define _GLIBCXX_MOF_CV const -#include "mofunc_impl.h" -#define _GLIBCXX_MOF_REF & -#include "mofunc_impl.h" -#define _GLIBCXX_MOF_REF && -#include "mofunc_impl.h" -#define _GLIBCXX_MOF_CV const -#define _GLIBCXX_MOF_REF & -#include "mofunc_impl.h" -#define _GLIBCXX_MOF_CV const -#define _GLIBCXX_MOF_REF && -#include "mofunc_impl.h" - -#endif // __glibcxx_move_only_function -#endif // _GLIBCXX_MOVE_ONLY_FUNCTION_H diff --git a/libstdc++-v3/include/bits/predefined_ops.h b/libstdc++-v3/include/bits/predefined_ops.h index 5759ebd..d75b5c2 100644 --- a/libstdc++-v3/include/bits/predefined_ops.h +++ b/libstdc++-v3/include/bits/predefined_ops.h @@ -30,376 +30,178 @@ #ifndef _GLIBCXX_PREDEFINED_OPS_H #define _GLIBCXX_PREDEFINED_OPS_H 1 -#include <bits/move.h> +#include <bits/stl_function.h> // less<void>, equal_to<void> +#if __cplusplus >= 201103L +# include <type_traits> // is_empty, is_scalar, __conditional_t, __or_ +#else +# include <ext/type_traits.h> // __conditional_type +#endif namespace __gnu_cxx { namespace __ops { - struct _Iter_less_iter - { - template<typename _Iterator1, typename _Iterator2> - _GLIBCXX14_CONSTEXPR - bool - operator()(_Iterator1 __it1, _Iterator2 __it2) const - { return *__it1 < *__it2; } - }; - - _GLIBCXX14_CONSTEXPR - inline _Iter_less_iter - __iter_less_iter() - { return _Iter_less_iter(); } - - struct _Iter_less_val - { -#if __cplusplus >= 201103L - constexpr _Iter_less_val() = default; -#else - _Iter_less_val() { } -#endif + // These two explicit specializations are always defined by libstdc++, + // even when __cpp_lib_transparent_operators is not defined. + typedef std::equal_to<void> equal_to; + typedef std::less<void> less; - _GLIBCXX20_CONSTEXPR - explicit - _Iter_less_val(_Iter_less_iter) { } - - template<typename _Iterator, typename _Value> - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator __it, _Value& __val) const - { return *__it < __val; } - }; - - _GLIBCXX20_CONSTEXPR - inline _Iter_less_val - __iter_less_val() - { return _Iter_less_val(); } - - _GLIBCXX20_CONSTEXPR - inline _Iter_less_val - __iter_comp_val(_Iter_less_iter) - { return _Iter_less_val(); } - - struct _Val_less_iter - { #if __cplusplus >= 201103L - constexpr _Val_less_iter() = default; -#else - _Val_less_iter() { } -#endif - _GLIBCXX20_CONSTEXPR - explicit - _Val_less_iter(_Iter_less_iter) { } - - template<typename _Value, typename _Iterator> - _GLIBCXX20_CONSTEXPR - bool - operator()(_Value& __val, _Iterator __it) const - { return __val < *__it; } - }; - - _GLIBCXX20_CONSTEXPR - inline _Val_less_iter - __val_less_iter() - { return _Val_less_iter(); } - - _GLIBCXX20_CONSTEXPR - inline _Val_less_iter - __val_comp_iter(_Iter_less_iter) - { return _Val_less_iter(); } - - struct _Iter_equal_to_iter - { - template<typename _Iterator1, typename _Iterator2> - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator1 __it1, _Iterator2 __it2) const - { return *__it1 == *__it2; } - }; - - _GLIBCXX20_CONSTEXPR - inline _Iter_equal_to_iter - __iter_equal_to_iter() - { return _Iter_equal_to_iter(); } - - struct _Iter_equal_to_val - { - template<typename _Iterator, typename _Value> - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator __it, _Value& __val) const - { return *__it == __val; } - }; - - _GLIBCXX20_CONSTEXPR - inline _Iter_equal_to_val - __iter_equal_to_val() - { return _Iter_equal_to_val(); } - - _GLIBCXX20_CONSTEXPR - inline _Iter_equal_to_val - __iter_comp_val(_Iter_equal_to_iter) - { return _Iter_equal_to_val(); } - - template<typename _Compare> - struct _Iter_comp_iter - { - _Compare _M_comp; - - explicit _GLIBCXX14_CONSTEXPR - _Iter_comp_iter(_Compare __comp) - : _M_comp(_GLIBCXX_MOVE(__comp)) - { } - - template<typename _Iterator1, typename _Iterator2> - _GLIBCXX14_CONSTEXPR - bool - operator()(_Iterator1 __it1, _Iterator2 __it2) - { return bool(_M_comp(*__it1, *__it2)); } - }; + template<typename _Fn> + using __by_ref_or_value_fn + = std::__conditional_t<std::__or_<std::is_empty<_Fn>, + std::is_scalar<_Fn>>::value, + _Fn, _Fn&>; - template<typename _Compare> - _GLIBCXX14_CONSTEXPR - inline _Iter_comp_iter<_Compare> - __iter_comp_iter(_Compare __comp) - { return _Iter_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } + // More generic replacements for the deprecated utilities + // std::bind1st, std::bind2nd, and std::not1. + // These aren't fully "transparent" like std::less<void> because they + // do not use perfect forwarding, everything is treated as an lvalue. - template<typename _Compare> - struct _Iter_comp_val + template<typename _Func, typename _Value, bool _Val_2nd = false> + struct _Comp_with_val { - _Compare _M_comp; - - _GLIBCXX20_CONSTEXPR - explicit - _Iter_comp_val(_Compare __comp) - : _M_comp(_GLIBCXX_MOVE(__comp)) - { } - - _GLIBCXX20_CONSTEXPR - explicit - _Iter_comp_val(const _Iter_comp_iter<_Compare>& __comp) - : _M_comp(__comp._M_comp) - { } - -#if __cplusplus >= 201103L - _GLIBCXX20_CONSTEXPR - explicit - _Iter_comp_val(_Iter_comp_iter<_Compare>&& __comp) - : _M_comp(std::move(__comp._M_comp)) - { } -#endif - - template<typename _Iterator, typename _Value> - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator __it, _Value& __val) - { return bool(_M_comp(*__it, __val)); } + using _Fn = __by_ref_or_value_fn<_Func>; + + explicit constexpr + _Comp_with_val(_Fn __f, const _Value& __v) + : _M_f(__f), _M_val(__v) { } + + [[__no_unique_address__]] _Fn _M_f; + const _Value& _M_val; + + template<typename _Tp> + _GLIBCXX14_CONSTEXPR bool + operator()(_Tp&& __arg) + { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++17-extensions" + if constexpr (_Val_2nd) + return _M_f(__arg, _M_val); + else + return _M_f(_M_val, __arg); +#pragma GCC diagnostic pop + } }; - template<typename _Compare> - _GLIBCXX20_CONSTEXPR - inline _Iter_comp_val<_Compare> - __iter_comp_val(_Compare __comp) - { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); } - - template<typename _Compare> - _GLIBCXX20_CONSTEXPR - inline _Iter_comp_val<_Compare> - __iter_comp_val(_Iter_comp_iter<_Compare> __comp) - { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); } + template<typename _Func, typename _Value> + using _Comp_with_val_1st = _Comp_with_val<_Func, _Value, false>; + template<typename _Func, typename _Value> + using _Comp_with_val_2nd = _Comp_with_val<_Func, _Value, true>; - template<typename _Compare> - struct _Val_comp_iter + template<typename _Func> + struct _Unary_negate { - _Compare _M_comp; + using _Fn = __by_ref_or_value_fn<_Func>; - _GLIBCXX20_CONSTEXPR - explicit - _Val_comp_iter(_Compare __comp) - : _M_comp(_GLIBCXX_MOVE(__comp)) - { } - - _GLIBCXX20_CONSTEXPR - explicit - _Val_comp_iter(const _Iter_comp_iter<_Compare>& __comp) - : _M_comp(__comp._M_comp) - { } + explicit constexpr + _Unary_negate(_Fn __f) : _M_f(__f) { } -#if __cplusplus >= 201103L - _GLIBCXX20_CONSTEXPR - explicit - _Val_comp_iter(_Iter_comp_iter<_Compare>&& __comp) - : _M_comp(std::move(__comp._M_comp)) - { } -#endif + [[__no_unique_address__]] _Fn _M_f; - template<typename _Value, typename _Iterator> - _GLIBCXX20_CONSTEXPR - bool - operator()(_Value& __val, _Iterator __it) - { return bool(_M_comp(__val, *__it)); } + template<typename _Tp> + _GLIBCXX14_CONSTEXPR bool + operator()(_Tp&& __arg) { return !_M_f(__arg); } }; - template<typename _Compare> - _GLIBCXX20_CONSTEXPR - inline _Val_comp_iter<_Compare> - __val_comp_iter(_Compare __comp) - { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } + template<typename _Func> + constexpr _Unary_negate<_Func> + not1(_Func& __f) + { return _Unary_negate<_Func>(__f); } - template<typename _Compare> - _GLIBCXX20_CONSTEXPR - inline _Val_comp_iter<_Compare> - __val_comp_iter(_Iter_comp_iter<_Compare> __comp) - { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } +#else // <= C++11 - template<typename _Value> - struct _Iter_equals_val - { - _Value& _M_value; + template<typename _Fn> + struct __by_ref_or_value_fn + : __conditional_type<__is_empty(_Fn), _Fn, _Fn&> + { }; - _GLIBCXX20_CONSTEXPR - explicit - _Iter_equals_val(_Value& __value) - : _M_value(__value) - { } - - template<typename _Iterator> - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator __it) - { return *__it == _M_value; } - }; + template<typename _Fn> + struct __by_ref_or_value_fn<_Fn*> + { typedef _Fn* __type; }; - template<typename _Value> - _GLIBCXX20_CONSTEXPR - inline _Iter_equals_val<_Value> - __iter_equals_val(_Value& __val) - { return _Iter_equals_val<_Value>(__val); } + // We don't use std::binder1st, std::binder2nd, or std::unary_negate here + // because they require adaptable function objects, i.e. types with nested + // result_type and argument_type/first_argument_type/second_argument_type. - template<typename _Iterator1> - struct _Iter_equals_iter + template<typename _Func, typename _Value> + struct _Comp_with_val_1st { - _Iterator1 _M_it1; + typedef typename __by_ref_or_value_fn<_Func>::__type _Fn; - _GLIBCXX20_CONSTEXPR explicit - _Iter_equals_iter(_Iterator1 __it1) - : _M_it1(__it1) - { } + _Comp_with_val_1st(_Fn __f, const _Value& __v) + : _M_f(__f), _M_val(__v) { } - template<typename _Iterator2> - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator2 __it2) - { return *__it2 == *_M_it1; } - }; + _Fn _M_f; + const _Value& _M_val; - template<typename _Iterator> - _GLIBCXX20_CONSTEXPR - inline _Iter_equals_iter<_Iterator> - __iter_comp_iter(_Iter_equal_to_iter, _Iterator __it) - { return _Iter_equals_iter<_Iterator>(__it); } + template<typename _Tp> + bool operator()(_Tp& __arg) { return _M_f(_M_val, __arg); } + template<typename _Tp> + bool operator()(const _Tp& __arg) { return _M_f(_M_val, __arg); } + }; - template<typename _Predicate> - struct _Iter_pred + template<typename _Func, typename _Value> + struct _Comp_with_val_2nd { - _Predicate _M_pred; + typedef typename __by_ref_or_value_fn<_Func>::__type _Fn; - _GLIBCXX20_CONSTEXPR explicit - _Iter_pred(_Predicate __pred) - : _M_pred(_GLIBCXX_MOVE(__pred)) - { } - - template<typename _Iterator> - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator __it) - { return bool(_M_pred(*__it)); } - }; + _Comp_with_val_2nd(_Fn __f, const _Value& __v) + : _M_f(__f), _M_val(__v) { } - template<typename _Predicate> - _GLIBCXX20_CONSTEXPR - inline _Iter_pred<_Predicate> - __pred_iter(_Predicate __pred) - { return _Iter_pred<_Predicate>(_GLIBCXX_MOVE(__pred)); } + _Fn _M_f; + const _Value& _M_val; - template<typename _Compare, typename _Value> - struct _Iter_comp_to_val - { - _Compare _M_comp; - _Value& _M_value; - - _GLIBCXX20_CONSTEXPR - _Iter_comp_to_val(_Compare __comp, _Value& __value) - : _M_comp(_GLIBCXX_MOVE(__comp)), _M_value(__value) - { } - - template<typename _Iterator> - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator __it) - { return bool(_M_comp(*__it, _M_value)); } + template<typename _Tp> + bool operator()(_Tp& __arg) { return _M_f(__arg, _M_val); } + template<typename _Tp> + bool operator()(const _Tp& __arg) { return _M_f(__arg, _M_val); } }; - template<typename _Compare, typename _Value> - _Iter_comp_to_val<_Compare, _Value> - _GLIBCXX20_CONSTEXPR - __iter_comp_val(_Compare __comp, _Value &__val) + template<typename _Func> + struct _Unary_negate_1 // N.B. different name for C++98 to satisfy ODR { - return _Iter_comp_to_val<_Compare, _Value>(_GLIBCXX_MOVE(__comp), __val); - } + typedef typename __by_ref_or_value_fn<_Func>::__type _Fn; - template<typename _Compare, typename _Iterator1> - struct _Iter_comp_to_iter - { - _Compare _M_comp; - _Iterator1 _M_it1; + explicit _Unary_negate_1(_Fn __f) : _M_f(__f) { } - _GLIBCXX20_CONSTEXPR - _Iter_comp_to_iter(_Compare __comp, _Iterator1 __it1) - : _M_comp(_GLIBCXX_MOVE(__comp)), _M_it1(__it1) - { } + _Fn _M_f; - template<typename _Iterator2> - _GLIBCXX20_CONSTEXPR + template<typename _Tp> + bool + operator()(_Tp& __arg) { return !_M_f(__arg); } + template<typename _Tp> bool - operator()(_Iterator2 __it2) - { return bool(_M_comp(*__it2, *_M_it1)); } + operator()(const _Tp& __arg) { return !_M_f(__arg); } }; - template<typename _Compare, typename _Iterator> - _GLIBCXX20_CONSTEXPR - inline _Iter_comp_to_iter<_Compare, _Iterator> - __iter_comp_iter(_Iter_comp_iter<_Compare> __comp, _Iterator __it) - { - return _Iter_comp_to_iter<_Compare, _Iterator>( - _GLIBCXX_MOVE(__comp._M_comp), __it); - } + template<typename _Func> + inline _Unary_negate_1<_Func> + not1(_Func& __f) + { return _Unary_negate_1<_Func>(__f); } +#endif - template<typename _Predicate> - struct _Iter_negate - { - _Predicate _M_pred; + // N.B. these functions take lvalue references because we want to avoid + // returning a call wrapper that has a dangling reference to a prvalue. - _GLIBCXX20_CONSTEXPR - explicit - _Iter_negate(_Predicate __pred) - : _M_pred(_GLIBCXX_MOVE(__pred)) - { } + template<typename _Func, typename _Value> + _GLIBCXX_CONSTEXPR inline _Comp_with_val_1st<_Func, _Value> + bind1st(_Func& __f, const _Value& __val) + { return _Comp_with_val_1st<_Func, _Value>(__f, __val); } - template<typename _Iterator> - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator __it) - { return !bool(_M_pred(*__it)); } - }; + template<typename _Func, typename _Value> + _GLIBCXX_CONSTEXPR inline _Comp_with_val_2nd<_Func, _Value> + bind2nd(_Func& __f, const _Value& __val) + { return _Comp_with_val_2nd<_Func, _Value>(__f, __val); } - template<typename _Predicate> - _GLIBCXX20_CONSTEXPR - inline _Iter_negate<_Predicate> - __negate(_Iter_pred<_Predicate> __pred) - { return _Iter_negate<_Predicate>(_GLIBCXX_MOVE(__pred._M_pred)); } + // Equivalent to bind2nd(equal_to{}, val) + template<typename _Value> + _GLIBCXX_CONSTEXPR inline _Comp_with_val_2nd<equal_to, _Value> + __equal_to(const _Value& __val) + { return _Comp_with_val_2nd<equal_to, _Value>(equal_to(), __val); } } // namespace __ops } // namespace __gnu_cxx diff --git a/libstdc++-v3/include/bits/quoted_string.h b/libstdc++-v3/include/bits/quoted_string.h index 3a828d5..9a51aa3 100644 --- a/libstdc++-v3/include/bits/quoted_string.h +++ b/libstdc++-v3/include/bits/quoted_string.h @@ -61,6 +61,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Quoted_string& operator=(_Quoted_string&) = delete; + // Friends for ADL with module std. + template<typename _CharT2, typename _Traits> + friend std::basic_ostream<_CharT2, _Traits>& + operator<<(std::basic_ostream<_CharT2, _Traits>& __os, + const _Quoted_string<const _CharT2*, _CharT2>& __str); + + template<typename _CharT2, typename _Traits, typename _String2> + friend std::basic_ostream<_CharT2, _Traits>& + operator<<(std::basic_ostream<_CharT2, _Traits>& __os, + const _Quoted_string<_String2, _CharT2>& __str); + + template<typename _CharT2, typename _Traits, typename _Alloc> + friend std::basic_istream<_CharT2, _Traits>& + operator>>(std::basic_istream<_CharT2, _Traits>& __is, + const _Quoted_string<basic_string<_CharT2, _Traits, _Alloc>&, + _CharT2>& __str); + _String _M_string; _CharT _M_delim; _CharT _M_escape; @@ -78,6 +95,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Quoted_string& operator=(_Quoted_string&) = delete; + // Friend for ADL with module std. + template<typename _CharT2, typename _Traits2, typename _String2> + friend std::basic_ostream<_CharT2, _Traits2>& + operator<<(std::basic_ostream<_CharT2, _Traits2>& __os, + const _Quoted_string<_String2, _CharT2>& __str); + basic_string_view<_CharT, _Traits> _M_string; _CharT _M_delim; _CharT _M_escape; diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h index 1fdaf51..ebc863e 100644 --- a/libstdc++-v3/include/bits/random.h +++ b/libstdc++-v3/include/bits/random.h @@ -32,6 +32,7 @@ #define _RANDOM_H 1 #include <vector> +#include <bits/ios_base.h> #include <bits/uniform_int_dist.h> namespace std _GLIBCXX_VISIBILITY(default) @@ -1688,6 +1689,263 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return !(__lhs == __rhs); } #endif +#if __glibcxx_philox_engine // >= C++26 + /** + * @brief A discrete pseudorandom number generator with weak cryptographic + * properties + * + * This algorithm was designed to be used for highly parallel random number + * generation, and is capable of immensely long periods. It provides + * "Crush-resistance", denoting an ability to pass the TestU01 Suite's + * "Big Crush" test, demonstrating significant apparent entropy. + * + * It is not intended for cryptographic use and should not be used for such, + * despite being based on cryptographic primitives. + * + * The typedefs `philox4x32` and `philox4x64` are provided as suitable + * defaults for most use cases, providing high-quality random numbers + * with reasonable performance. + * + * This algorithm was created by John Salmon, Mark Moraes, Ron Dror, and + * David Shaw as a product of D.E. Shaw Research. + * + * @tparam __w Word size + * @tparam __n Buffer size + * @tparam __r Rounds + * @tparam __consts Multiplication and round constant pack, ordered as + * M_{0}, C_{0}, M_{1}, C_{1}, ... , M_{N/2-1}, C_{N/2-1} + * + * @headerfile random + * @since C++26 + */ + template<typename _UIntType, size_t __w, size_t __n, size_t __r, + _UIntType... __consts> + class philox_engine + { + static_assert(__n == 2 || __n == 4, + "template argument N must be either 2 or 4"); + static_assert(sizeof...(__consts) == __n, + "length of consts array must match specified N"); + static_assert(0 < __r, "a number of rounds must be specified"); + static_assert((0 < __w && __w <= numeric_limits<_UIntType>::digits), + "specified bitlength must match input type"); + + template<typename _Sseq> + static constexpr bool __is_seed_seq = requires { + typename __detail::_If_seed_seq_for<_Sseq, philox_engine, _UIntType>; + }; + + template <size_t __ind0, size_t __ind1> + static constexpr + array<_UIntType, __n / 2> + _S_popArray() + { + if constexpr (__n == 4) + return {__consts...[__ind0], __consts...[__ind1]}; + else + return {__consts...[__ind0]}; + } + + public: + using result_type = _UIntType; + // public members + static constexpr size_t word_size = __w; + static constexpr size_t word_count = __n; + static constexpr size_t round_count = __r; + static constexpr array<result_type, __n / 2> multipliers + = _S_popArray<0,2>(); + static constexpr array<result_type, __n / 2> round_consts + = _S_popArray<1,3>(); + + /// The minimum value that this engine can return + static constexpr result_type + min() + { return 0; } + + /// The maximum value that this engine can return + static constexpr result_type + max() + { + return ((1ull << (__w - 1)) | ((1ull << (__w - 1)) - 1)); + } + // default key value + static constexpr result_type default_seed = 20111115u; + + // constructors + philox_engine() + : philox_engine(default_seed) + { } + + explicit + philox_engine(result_type __value) + : _M_x{}, _M_k{}, _M_y{}, _M_i(__n - 1) + { _M_k[0] = __value & max(); } + + /** @brief seed sequence constructor for %philox_engine + * + * @param __q the seed sequence + */ + template<typename _Sseq> requires __is_seed_seq<_Sseq> + explicit + philox_engine(_Sseq& __q) + { + seed(__q); + } + + void + seed(result_type __value = default_seed) + { + _M_x = {}; + _M_y = {}; + _M_k = {}; + _M_k[0] = __value & max(); + _M_i = __n - 1; + } + + /** @brief seeds %philox_engine by seed sequence + * + * @param __q the seed sequence + */ + template<typename _Sseq> + void + seed(_Sseq& __q) requires __is_seed_seq<_Sseq>; + + /** @brief sets the internal counter "cleartext" + * + * @param __counter std::array of len N + */ + void + set_counter(const array<result_type, __n>& __counter) + { + for (size_t __j = 0; __j < __n; ++__j) + _M_x[__j] = __counter[__n - 1 - __j] & max(); + _M_i = __n - 1; + } + + /** @brief compares two %philox_engine objects + * + * @returns true if the objects will produce an identical stream, + * false otherwise + */ + friend bool + operator==(const philox_engine&, const philox_engine&) = default; + + /** @brief outputs a single w-bit number and handles state advancement + * + * @returns return_type + */ + result_type + operator()() + { + _M_transition(); + return _M_y[_M_i]; + } + + /** @brief discards __z numbers + * + * @param __z number of iterations to discard + */ + void + discard(unsigned long long __z) + { + while (__z--) + _M_transition(); + } + + /** @brief outputs the state of the generator + * + * @param __os An output stream. + * @param __x A %philox_engine object reference + * + * @returns the state of the Philox Engine in __os + */ + template<typename _CharT, typename _Traits> + friend basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __os, + const philox_engine& __x) + { + const typename ios_base::fmtflags __flags = __os.flags(); + const _CharT __fill = __os.fill(); + __os.flags(ios_base::dec | ios_base::left); + _CharT __space = __os.widen(' '); + __os.fill(__space); + for (auto& __subkey : __x._M_k) + __os << __subkey << __space; + for (auto& __ctr : __x._M_x) + __os << __ctr << __space; + __os << __x._M_i; + __os.flags(__flags); + __os.fill(__fill); + return __os; + } + + /** @brief takes input to set the state of the %philox_engine object + * + * @param __is An input stream. + * @param __x A %philox_engine object reference + * + * @returns %philox_engine object is set with values from instream + */ + template <typename _CharT, typename _Traits> + friend basic_istream<_CharT, _Traits>& + operator>>(basic_istream<_CharT, _Traits>& __is, + philox_engine& __x) + { + const typename ios_base::fmtflags __flags = __is.flags(); + __is.flags(ios_base::dec | ios_base::skipws); + for (auto& __subkey : __x._M_k) + __is >> __subkey; + for (auto& __ctr : __x._M_x) + __is >> __ctr; + array<_UIntType, __n> __tmpCtr = __x._M_x; + unsigned char __setIndex = 0; + for (size_t __j = 0; __j < __x._M_x.size(); ++__j) + { + if (__x._M_x[__j] > 0) + { + __setIndex = __j; + break; + } + } + for (size_t __j = 0; __j <= __setIndex; ++__j) + { + if (__j != __setIndex) + __x._M_x[__j] = max(); + else + --__x._M_x[__j]; + } + __x._M_philox(); + __x._M_x = __tmpCtr; + __is >> __x._M_i; + __is.flags(__flags); + return __is; + } + + private: + // private state variables + array<_UIntType, __n> _M_x; + array<_UIntType, __n / 2> _M_k; + array<_UIntType, __n> _M_y; + unsigned long long _M_i = 0; + + // The high W bits of the product of __a and __b + static _UIntType + _S_mulhi(_UIntType __a, _UIntType __b); // (A*B)/2^W + + // The low W bits of the product of __a and __b + static _UIntType + _S_mullo(_UIntType __a, _UIntType __b); // (A*B)%2^W + + // An R-round substitution/Feistel Network hybrid for philox_engine + void + _M_philox(); + + // The transition function + void + _M_transition(); + }; +#endif + /** * The classic Minimum Standard rand0 of Lewis, Goodman, and Miller. */ @@ -1742,6 +2000,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef minstd_rand0 default_random_engine; +#if __glibcxx_philox_engine + + /// 32-bit four-word Philox engine. + typedef philox_engine< + uint_fast32_t, + 32, 4, 10, + 0xCD9E8D57, 0x9E3779B9, + 0xD2511F53, 0xBB67AE85> philox4x32; + + /// 64-bit four-word Philox engine. + typedef philox_engine< + uint_fast64_t, + 64, 4, 10, + 0xCA5A826395121157, 0x9E3779B97F4A7C15, + 0xD2E7470EE14C6C93, 0xBB67AE8584CAA73B> philox4x64; +#endif + /** * A standard interface to a platform-specific non-deterministic * random number generator (if any are available). diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc index 53ccacb..b4273f0 100644 --- a/libstdc++-v3/include/bits/random.tcc +++ b/libstdc++-v3/include/bits/random.tcc @@ -83,7 +83,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __normalize(_InputIterator __first, _InputIterator __last, _OutputIterator __result, const _Tp& __factor) { - for (; __first != __last; ++__first, ++__result) + for (; __first != __last; ++__first, (void) ++__result) *__result = *__first / __factor; return __result; } @@ -907,6 +907,129 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __is; } +#if __glibcxx_philox_engine // >= C++26 + + template<typename _UIntType, size_t __w, size_t __n, size_t __r, + _UIntType... __consts> + _UIntType + philox_engine<_UIntType, __w, __n, __r, __consts...>:: + _S_mulhi(_UIntType __a, _UIntType __b) + { + const __uint128_t __num = + static_cast<__uint128_t>(__a) * static_cast<__uint128_t>(__b); + return static_cast<_UIntType>((__num >> __w) & max()); + } + + template<typename _UIntType, size_t __w, size_t __n, size_t __r, + _UIntType... __consts> + _UIntType + philox_engine<_UIntType, __w, __n, __r, __consts...>:: + _S_mullo(_UIntType __a, _UIntType __b) + { + return static_cast<_UIntType>((__a * __b) & max()); + } + + template<typename _UIntType, size_t __w, size_t __n, size_t __r, + _UIntType... __consts> + void + philox_engine<_UIntType, __w, __n, __r, __consts...>::_M_transition() + { + ++_M_i; + if (_M_i != __n) + return; + + _M_philox(); + if constexpr (__n == 4) + { + __uint128_t __uh = + (static_cast<__uint128_t>(_M_x[1]) << __w) + | (static_cast<__uint128_t>(_M_x[0]) + 1); + __uint128_t __lh = + ((static_cast<__uint128_t>(_M_x[3]) << __w) + | (_M_x[2])); + __uint128_t __bigMask = + (static_cast<__uint128_t>(1) << ((2 * __w) - 1)) + | ((static_cast<__uint128_t>(1) << ((2 * __w) - 1)) - 1); + if ((__uh & __bigMask) == 0) + { + ++__lh; + __uh = 0; + } + _M_x[0] = __uh & max(); + _M_x[1] = (__uh >> (__w)) & max(); + _M_x[2] = __lh & max(); + _M_x[3] = (__lh >> (__w)) & max(); + } + else + { + __uint128_t __num = + (static_cast<__uint128_t>(_M_x[1]) << __w) + | (static_cast<__uint128_t>(_M_x[0]) + 1); + _M_x[0] = __num & max(); + _M_x[1] = (__num >> __w) & max(); + } + _M_i = 0; + } + + template<typename _UIntType, size_t __w, size_t __n, size_t __r, + _UIntType... __consts> + void + philox_engine<_UIntType, __w, __n, __r, __consts...>::_M_philox() + { + array<_UIntType, __n> __outputSeq = _M_x; + for (size_t __j = 0; __j < __r; ++__j) + { + array<_UIntType, __n> __intermedSeq{}; + if constexpr (__n == 4) + { + __intermedSeq[0] = __outputSeq[2]; + __intermedSeq[1] = __outputSeq[1]; + __intermedSeq[2] = __outputSeq[0]; + __intermedSeq[3] = __outputSeq[3]; + } + else + { + __intermedSeq[0] = __outputSeq[0]; + __intermedSeq[1] = __outputSeq[1]; + } + for (unsigned long __k = 0; __k < (__n/2); ++__k) + { + __outputSeq[2*__k] + = _S_mulhi(__intermedSeq[2*__k], multipliers[__k]) + ^ (((_M_k[__k] + (__j * round_consts[__k])) & max())) + ^ __intermedSeq[2*__k+1]; + + __outputSeq[(2*__k)+1] + = _S_mullo(__intermedSeq[2*__k], multipliers[__k]); + } + } + _M_y = __outputSeq; + } + + template<typename _UIntType, size_t __w, size_t __n, size_t __r, + _UIntType... __consts> + template<typename _Sseq> + void + philox_engine<_UIntType, __w, __n, __r, __consts...>::seed(_Sseq& __q) + requires __is_seed_seq<_Sseq> + { + seed(0); + + const unsigned __p = 1 + ((__w - 1) / 32); + uint_least32_t __tmpArr[(__n/2) * __p]; + __q.generate(__tmpArr + 0, __tmpArr + ((__n/2) * __p)); + for (unsigned __k = 0; __k < (__n/2); ++__k) + { + unsigned long long __precalc = 0; + for (unsigned __j = 0; __j < __p; ++__j) + { + unsigned long long __multiplicand = (1ull << (32 * __j)); + __precalc += (__tmpArr[__k * __p + __j] * __multiplicand) & max(); + } + _M_k[__k] = __precalc; + } + } +#endif // philox_engine template<typename _IntType, typename _CharT, typename _Traits> std::basic_ostream<_CharT, _Traits>& @@ -3078,7 +3201,7 @@ namespace __detail _InputIteratorW __wbegin) : _M_int(), _M_den(), _M_cp(), _M_m() { - for (; __bbegin != __bend; ++__bbegin, ++__wbegin) + for (; __bbegin != __bend; ++__bbegin, (void) ++__wbegin) { _M_int.push_back(*__bbegin); _M_den.push_back(*__wbegin); diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h index f36e7dd..5c9fe62 100644 --- a/libstdc++-v3/include/bits/ranges_algo.h +++ b/libstdc++-v3/include/bits/ranges_algo.h @@ -32,6 +32,7 @@ #if __cplusplus > 201703L +#include <bit> // __bit_width #if __cplusplus > 202002L #include <optional> #endif @@ -47,28 +48,60 @@ namespace ranges { namespace __detail { + template<typename _Fp> + using __by_ref_or_value_fn + = __conditional_t<is_scalar_v<_Fp> || is_empty_v<_Fp>, _Fp, _Fp&>; + template<typename _Comp, typename _Proj> - constexpr auto + struct _Comp_proj + { + [[no_unique_address]] __by_ref_or_value_fn<_Comp> _M_comp; + [[no_unique_address]] __by_ref_or_value_fn<_Proj> _M_proj; + + constexpr + _Comp_proj(_Comp& __comp, _Proj& __proj) + : _M_comp(__comp), _M_proj(__proj) + { } + + template<typename _Tp, typename _Up> + constexpr bool + operator()(_Tp&& __x, _Up&& __y) + { + return std::__invoke(_M_comp, + std::__invoke(_M_proj, std::forward<_Tp>(__x)), + std::__invoke(_M_proj, std::forward<_Up>(__y))); + } + }; + + template<typename _Comp, typename _Proj> + constexpr _Comp_proj<_Comp, _Proj> __make_comp_proj(_Comp& __comp, _Proj& __proj) + { return {__comp, __proj}; } + + template<typename _Pred, typename _Proj> + struct _Pred_proj { - return [&] (auto&& __lhs, auto&& __rhs) -> bool { - using _TL = decltype(__lhs); - using _TR = decltype(__rhs); - return std::__invoke(__comp, - std::__invoke(__proj, std::forward<_TL>(__lhs)), - std::__invoke(__proj, std::forward<_TR>(__rhs))); - }; - } + [[no_unique_address]] __by_ref_or_value_fn<_Pred> _M_pred; + [[no_unique_address]] __by_ref_or_value_fn<_Proj> _M_proj; + + constexpr + _Pred_proj(_Pred& __pred, _Proj& __proj) + : _M_pred(__pred), _M_proj(__proj) + { } + + template<typename _Tp> + constexpr bool + operator()(_Tp&& __x) + { + return std::__invoke(_M_pred, + std::__invoke(_M_proj, std::forward<_Tp>(__x))); + } + }; template<typename _Pred, typename _Proj> - constexpr auto + constexpr _Pred_proj<_Pred, _Proj> __make_pred_proj(_Pred& __pred, _Proj& __proj) - { - return [&] <typename _Tp> (_Tp&& __arg) -> bool { - return std::__invoke(__pred, - std::__invoke(__proj, std::forward<_Tp>(__arg))); - }; - } + { return {__pred, __proj}; } } // namespace __detail struct __all_of_fn @@ -76,7 +109,7 @@ namespace ranges template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { @@ -89,7 +122,7 @@ namespace ranges template<input_range _Range, typename _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -104,7 +137,7 @@ namespace ranges template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { @@ -117,7 +150,7 @@ namespace ranges template<input_range _Range, typename _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -132,7 +165,7 @@ namespace ranges template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { @@ -145,7 +178,7 @@ namespace ranges template<input_range _Range, typename _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -246,7 +279,7 @@ namespace ranges typename _Pred = ranges::equal_to, typename _Proj1 = identity, typename _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - constexpr _Iter1 + [[nodiscard]] constexpr _Iter1 operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const @@ -265,7 +298,7 @@ namespace ranges typename _Proj1 = identity, typename _Proj2 = identity> requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - constexpr borrowed_iterator_t<_Range1> + [[nodiscard]] constexpr borrowed_iterator_t<_Range1> operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { @@ -286,7 +319,7 @@ namespace ranges requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Tp*> - constexpr iter_difference_t<_Iter> + [[nodiscard]] constexpr iter_difference_t<_Iter> operator()(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) const { @@ -303,7 +336,7 @@ namespace ranges requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Tp*> - constexpr range_difference_t<_Range> + [[nodiscard]] constexpr range_difference_t<_Range> operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -438,6 +471,254 @@ namespace ranges inline constexpr __search_n_fn search_n{}; +#if __glibcxx_ranges_starts_ends_with // C++ >= 23 + struct __starts_with_fn + { + template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + iter_difference_t<_Iter1> __n1 = -1; + iter_difference_t<_Iter2> __n2 = -1; + if constexpr (sized_sentinel_for<_Sent1, _Iter1>) + __n1 = __last1 - __first1; + if constexpr (sized_sentinel_for<_Sent2, _Iter2>) + __n2 = __last2 - __first2; + return _S_impl(std::move(__first1), __last1, __n1, + std::move(__first2), __last2, __n2, + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + + template<input_range _Range1, input_range _Range2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + range_difference_t<_Range1> __n1 = -1; + range_difference_t<_Range2> __n2 = -1; + if constexpr (sized_range<_Range1>) + __n1 = ranges::size(__r1); + if constexpr (sized_range<_Range2>) + __n2 = ranges::size(__r2); + return _S_impl(ranges::begin(__r1), ranges::end(__r1), __n1, + ranges::begin(__r2), ranges::end(__r2), __n2, + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + + private: + template<typename _Iter1, typename _Sent1, typename _Iter2, typename _Sent2, + typename _Pred, + typename _Proj1, typename _Proj2> + static constexpr bool + _S_impl(_Iter1 __first1, _Sent1 __last1, iter_difference_t<_Iter1> __n1, + _Iter2 __first2, _Sent2 __last2, iter_difference_t<_Iter2> __n2, + _Pred __pred, _Proj1 __proj1, _Proj2 __proj2) + { + if (__first2 == __last2) [[unlikely]] + return true; + else if (__n1 == -1 || __n2 == -1) + return ranges::mismatch(std::move(__first1), __last1, + std::move(__first2), __last2, + std::move(__pred), + std::move(__proj1), std::move(__proj2)).in2 == __last2; + else if (__n1 < __n2) + return false; + else if constexpr (random_access_iterator<_Iter1>) + return ranges::equal(__first1, __first1 + iter_difference_t<_Iter1>(__n2), + std::move(__first2), __last2, + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + else + return ranges::equal(counted_iterator(std::move(__first1), + iter_difference_t<_Iter1>(__n2)), + default_sentinel, + std::move(__first2), __last2, + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + + friend struct __ends_with_fn; + }; + + inline constexpr __starts_with_fn starts_with{}; + + struct __ends_with_fn + { + template<input_iterator _Iter1, sentinel_for<_Iter1> _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires (forward_iterator<_Iter1> || sized_sentinel_for<_Sent1, _Iter1>) + && (forward_iterator<_Iter2> || sized_sentinel_for<_Sent2, _Iter2>) + && indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + iter_difference_t<_Iter1> __n1 = -1; + iter_difference_t<_Iter2> __n2 = -1; + if constexpr (sized_sentinel_for<_Sent1, _Iter1>) + __n1 = __last1 - __first1; + if constexpr (sized_sentinel_for<_Sent2, _Iter2>) + __n2 = __last2 - __first2; + return _S_impl(std::move(__first1), __last1, __n1, + std::move(__first2), __last2, __n2, + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + + template<input_range _Range1, input_range _Range2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires (forward_range<_Range1> || sized_range<_Range1>) + && (forward_range<_Range2> || sized_range<_Range2>) + && indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + range_difference_t<_Range1> __n1 = -1; + range_difference_t<_Range2> __n2 = -1; + if constexpr (sized_range<_Range1>) + __n1 = ranges::size(__r1); + if constexpr (sized_range<_Range2>) + __n2 = ranges::size(__r2); + return _S_impl(ranges::begin(__r1), ranges::end(__r1), __n1, + ranges::begin(__r2), ranges::end(__r2), __n2, + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + + private: + template<typename _Iter1, typename _Sent1, + typename _Iter2, typename _Sent2, + typename _Pred, + typename _Proj1, typename _Proj2> + static constexpr bool + _S_impl(_Iter1 __first1, _Sent1 __last1, iter_difference_t<_Iter1> __n1, + _Iter2 __first2, _Sent2 __last2, iter_difference_t<_Iter2> __n2, + _Pred __pred, _Proj1 __proj1, _Proj2 __proj2) + { + if constexpr (!random_access_iterator<_Iter1> + && bidirectional_iterator<_Iter1> && same_as<_Iter1, _Sent1> + && bidirectional_iterator<_Iter2> && same_as<_Iter2, _Sent2>) + return starts_with._S_impl(std::make_reverse_iterator(__last1), + std::make_reverse_iterator(__first1), + __n1, + std::make_reverse_iterator(__last2), + std::make_reverse_iterator(__first2), + __n2, + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + + if (__first2 == __last2) [[unlikely]] + return true; + + if constexpr (forward_iterator<_Iter2>) + if (__n2 == -1) + __n2 = ranges::distance(__first2, __last2); + + // __glibcxx_assert(__n2 != -1); + + if (__n1 != -1) + { + if (__n1 < __n2) + return false; + auto __shift = __n1 - iter_difference_t<_Iter1>(__n2); + if (random_access_iterator<_Iter1> + || !bidirectional_iterator<_Iter1> + || !same_as<_Iter1, _Sent1> + || __shift < __n2) + { + ranges::advance(__first1, __shift); + return ranges::equal(std::move(__first1), __last1, + std::move(__first2), __last2, + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + } + + if constexpr (bidirectional_iterator<_Iter1> && same_as<_Iter1, _Sent1>) + { + _Iter1 __it1 = __last1; + if (__n1 != -1) + ranges::advance(__it1, -iter_difference_t<_Iter1>(__n2)); + else + { + // We can't use ranges::advance if the haystack size is + // unknown, since we need to detect and return false if + // it's smaller than the needle. + iter_difference_t<_Iter2> __m = __n2; + while (__m != 0 && __it1 != __first1) + { + --__m; + --__it1; + } + if (__m != 0) + return false; + } + return ranges::equal(__it1, __last1, + std::move(__first2), __last2, + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + else if constexpr (forward_iterator<_Iter1>) + { + // __glibcxx_assert(__n1 == -1); + _Iter1 __prev_first1; + __n1 = 0; + while (true) + { + iter_difference_t<_Iter2> __m = __n2; + _Iter1 __it1 = __first1; + while (__m != 0 && __it1 != __last1) + { + ++__n1; + --__m; + ++__it1; + } + if (__m != 0) + { + // __glibcxx_assert(__it1 == __last1); + if (__n1 < __n2) + return false; + __first1 = ranges::next(__prev_first1, + iter_difference_t<_Iter1>(__n2 - __m)); + break; + } + __prev_first1 = __first1; + __first1 = __it1; + } + return ranges::equal(__first1, __last1, + std::move(__first2), __last2, + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + else + // If the haystack is non-forward then it must be sized, in which case + // we already returned via the __n1 != 1 case. + __builtin_unreachable(); + } + + }; + + inline constexpr __ends_with_fn ends_with{}; +#endif // __glibcxx_ranges_starts_ends_with + struct __find_end_fn { template<forward_iterator _Iter1, sentinel_for<_Iter1> _Sent1, @@ -445,7 +726,7 @@ namespace ranges typename _Pred = ranges::equal_to, typename _Proj1 = identity, typename _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - constexpr subrange<_Iter1> + [[nodiscard]] constexpr subrange<_Iter1> operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const @@ -502,7 +783,7 @@ namespace ranges typename _Proj1 = identity, typename _Proj2 = identity> requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - constexpr borrowed_subrange_t<_Range1> + [[nodiscard]] constexpr borrowed_subrange_t<_Range1> operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { @@ -525,7 +806,7 @@ namespace ranges indirect_equivalence_relation<projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>> _Pred = ranges::equal_to> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const @@ -594,7 +875,7 @@ namespace ranges indirect_equivalence_relation< projected<iterator_t<_Range1>, _Proj1>, projected<iterator_t<_Range2>, _Proj2>> _Pred = ranges::equal_to> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { @@ -1000,7 +1281,7 @@ namespace ranges template<permutable _Iter, sentinel_for<_Iter> _Sent, typename _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - constexpr subrange<_Iter> + [[nodiscard]] constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { @@ -1013,7 +1294,7 @@ namespace ranges for (; __first != __last; ++__first) if (!std::__invoke(__pred, std::__invoke(__proj, *__first))) { - *__result = std::move(*__first); + *__result = ranges::iter_move(__first); ++__result; } @@ -1024,7 +1305,7 @@ namespace ranges indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> requires permutable<iterator_t<_Range>> - constexpr borrowed_subrange_t<_Range> + [[nodiscard]] constexpr borrowed_subrange_t<_Range> operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -1042,7 +1323,7 @@ namespace ranges requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Tp*> - constexpr subrange<_Iter> + [[nodiscard]] constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) const { @@ -1060,7 +1341,7 @@ namespace ranges && indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Tp*> - constexpr borrowed_subrange_t<_Range> + [[nodiscard]] constexpr borrowed_subrange_t<_Range> operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -1159,7 +1440,7 @@ namespace ranges typename _Proj = identity, indirect_equivalence_relation< projected<_Iter, _Proj>> _Comp = ranges::equal_to> - constexpr subrange<_Iter> + [[nodiscard]] constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { @@ -1173,7 +1454,7 @@ namespace ranges if (!std::__invoke(__comp, std::__invoke(__proj, *__dest), std::__invoke(__proj, *__first))) - *++__dest = std::move(*__first); + *++__dest = ranges::iter_move(__first); return {++__dest, __first}; } @@ -1181,7 +1462,7 @@ namespace ranges indirect_equivalence_relation< projected<iterator_t<_Range>, _Proj>> _Comp = ranges::equal_to> requires permutable<iterator_t<_Range>> - constexpr borrowed_subrange_t<_Range> + [[nodiscard]] constexpr borrowed_subrange_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -1218,6 +1499,9 @@ namespace ranges if (__first == __last) return {std::move(__first), std::move(__result)}; + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4269. unique_copy passes arguments to its predicate backwards + // TODO: perform a closer comparison with reference implementations if constexpr (forward_iterator<_Iter>) { @@ -1245,13 +1529,13 @@ namespace ranges } else // indirectly_copyable_storable<_Iter, _Out> { - auto __value = *__first; + iter_value_t<_Iter> __value(*__first); *__result = __value; while (++__first != __last) { if (!(bool)std::__invoke(__comp, - std::__invoke(__proj, *__first), - std::__invoke(__proj, __value))) + std::__invoke(__proj, __value), + std::__invoke(__proj, *__first))) { __value = *__first; *++__result = __value; @@ -1399,9 +1683,11 @@ namespace ranges if constexpr (__is_pod(iter_value_t<_Iter>)) if (__k == 1) { - auto __t = std::move(*__p); - ranges::move(__p + 1, __p + __n, __p); - *(__p + __n - 1) = std::move(__t); + auto __mid = ranges::next(__p, __n - 1); + auto __end = ranges::next(__mid); + iter_value_t<_Iter> __t(ranges::iter_move(__p)); + ranges::move(ranges::next(__p), __end, __p); + *__mid = std::move(__t); return {std::move(__ret), std::move(__lasti)}; } auto __q = __p + __k; @@ -1425,8 +1711,10 @@ namespace ranges if constexpr (__is_pod(iter_value_t<_Iter>)) if (__k == 1) { - auto __t = std::move(*(__p + __n - 1)); - ranges::move_backward(__p, __p + __n - 1, __p + __n); + auto __mid = ranges::next(__p, __n - 1); + auto __end = ranges::next(__mid); + iter_value_t<_Iter> __t(ranges::iter_move(__mid)); + ranges::move_backward(__p, __mid, __end); *__p = std::move(__t); return {std::move(__ret), std::move(__lasti)}; } @@ -1555,14 +1843,70 @@ namespace ranges operator()(_Iter __first, _Sent __last, _Out __out, iter_difference_t<_Iter> __n, _Gen&& __g) const { + // FIXME: Correctly handle integer-class difference types. if constexpr (forward_iterator<_Iter>) { - // FIXME: Forwarding to std::sample here requires computing __lasti - // which may take linear time. - auto __lasti = ranges::next(__first, __last); - return _GLIBCXX_STD_A:: - sample(std::move(__first), std::move(__lasti), std::move(__out), - __n, std::forward<_Gen>(__g)); + using _Size = iter_difference_t<_Iter>; + using __distrib_type = uniform_int_distribution<_Size>; + using __param_type = typename __distrib_type::param_type; + using _USize = __detail::__make_unsigned_like_t<_Size>; + using __uc_type + = common_type_t<typename remove_reference_t<_Gen>::result_type, _USize>; + + if (__first == __last) + return __out; + + __distrib_type __d{}; + _Size __unsampled_sz = ranges::distance(__first, __last); + __n = std::min(__n, __unsampled_sz); + + // If possible, we use __gen_two_uniform_ints to efficiently produce + // two random numbers using a single distribution invocation: + + const __uc_type __urngrange = __g.max() - __g.min(); + if (__urngrange / __uc_type(__unsampled_sz) >= __uc_type(__unsampled_sz)) + // I.e. (__urngrange >= __unsampled_sz * __unsampled_sz) but without + // wrapping issues. + { + while (__n != 0 && __unsampled_sz >= 2) + { + const pair<_Size, _Size> __p = + __gen_two_uniform_ints(__unsampled_sz, __unsampled_sz - 1, __g); + + --__unsampled_sz; + if (__p.first < __n) + { + *__out = *__first; + ++__out; + --__n; + } + + ++__first; + + if (__n == 0) break; + + --__unsampled_sz; + if (__p.second < __n) + { + *__out = *__first; + ++__out; + --__n; + } + + ++__first; + } + } + + // The loop above is otherwise equivalent to this one-at-a-time version: + + for (; __n != 0; ++__first) + if (__d(__g, __param_type{0, --__unsampled_sz}) < __n) + { + *__out = *__first; + ++__out; + --__n; + } + return __out; } else { @@ -1583,7 +1927,7 @@ namespace ranges if (__k < __n) __out[__k] = *__first; } - return __out + __sample_sz; + return __out + iter_difference_t<_Out>(__sample_sz); } } @@ -1612,9 +1956,66 @@ namespace ranges _Iter operator()(_Iter __first, _Sent __last, _Gen&& __g) const { - auto __lasti = ranges::next(__first, __last); - std::shuffle(std::move(__first), __lasti, std::forward<_Gen>(__g)); - return __lasti; + // FIXME: Correctly handle integer-class difference types. + if (__first == __last) + return __first; + + using _DistanceType = iter_difference_t<_Iter>; + using __ud_type = __detail::__make_unsigned_like_t<_DistanceType>; + using __distr_type = std::uniform_int_distribution<__ud_type>; + using __p_type = typename __distr_type::param_type; + + using __uc_type + = common_type_t<typename remove_reference_t<_Gen>::result_type, __ud_type>; + + if constexpr (sized_sentinel_for<_Sent, _Iter>) + { + const __uc_type __urngrange = __g.max() - __g.min(); + const __uc_type __urange = __uc_type(__last - __first); + + if (__urngrange / __urange >= __urange) + // I.e. (__urngrange >= __urange * __urange) but without wrap issues. + { + _Iter __i = ranges::next(__first); + + // Since we know the range isn't empty, an even number of elements + // means an uneven number of elements /to swap/, in which case we + // do the first one up front: + + if ((__urange % 2) == 0) + { + __distr_type __d{0, 1}; + ranges::iter_swap(__i++, ranges::next(__first, __d(__g))); + } + + // Now we know that __last - __i is even, so we do the rest in pairs, + // using a single distribution invocation to produce swap positions + // for two successive elements at a time: + + while (__i != __last) + { + const __uc_type __swap_range = __uc_type(__i - __first) + 1; + + const pair<_DistanceType, _DistanceType> __pospos = + __gen_two_uniform_ints(__swap_range, __swap_range + 1, __g); + + ranges::iter_swap(__i++, ranges::next(__first, __pospos.first)); + ranges::iter_swap(__i++, ranges::next(__first, __pospos.second)); + } + + return __i; + } + } + + __distr_type __d; + + _Iter __i = ranges::next(__first); + for (; __i != __last; ++__i) + ranges::iter_swap(__i, + ranges::next(__first, + __d(__g, __p_type(0, __i - __first)))); + + return __i; } template<random_access_range _Range, typename _Gen> @@ -1623,13 +2024,42 @@ namespace ranges borrowed_iterator_t<_Range> operator()(_Range&& __r, _Gen&& __g) const { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::forward<_Gen>(__g)); + if constexpr (sized_range<_Range> + && !sized_sentinel_for<sentinel_t<_Range>, + iterator_t<_Range>>) + return (*this)(ranges::begin(__r), + ranges::begin(__r) + ranges::distance(__r), + std::forward<_Gen>(__g)); + else + return (*this)(ranges::begin(__r), ranges::end(__r), + std::forward<_Gen>(__g)); } }; inline constexpr __shuffle_fn shuffle{}; + namespace __detail + { + template<typename _Iter, typename _Comp> + constexpr void + __push_heap(_Iter __first, + iter_difference_t<_Iter> __holeIndex, + iter_difference_t<_Iter> __topIndex, + iter_value_t<_Iter> __value, + _Comp __comp) + { + auto __parent = (__holeIndex - 1) / 2; + while (__holeIndex > __topIndex + && __comp(*(__first + __parent), __value)) + { + *(__first + __holeIndex) = ranges::iter_move(__first + __parent); + __holeIndex = __parent; + __parent = (__holeIndex - 1) / 2; + } + *(__first + __holeIndex) = std::move(__value); + } + } // namespace __detail + struct __push_heap_fn { template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent, @@ -1639,10 +2069,17 @@ namespace ranges operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { - auto __lasti = ranges::next(__first, __last); - std::push_heap(__first, __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; + if constexpr (!same_as<_Iter, _Sent>) + return (*this)(__first, ranges::next(__first, __last), + std::move(__comp), std::move(__proj)); + else + { + auto __comp_proj = __detail::__make_comp_proj(__comp, __proj); + iter_value_t<_Iter> __value(ranges::iter_move(ranges::prev(__last))); + __detail::__push_heap(__first, (__last - __first) - 1, + 0, std::move(__value), __comp_proj); + return __last; + } } template<random_access_range _Range, @@ -1658,6 +2095,48 @@ namespace ranges inline constexpr __push_heap_fn push_heap{}; + namespace __detail + { + template<typename _Iter, typename _Comp> + constexpr void + __adjust_heap(_Iter __first, + iter_difference_t<_Iter> __holeIndex, + iter_difference_t<_Iter> __len, + iter_value_t<_Iter> __value, + _Comp __comp) + { + auto __topIndex = __holeIndex; + auto __secondChild = __holeIndex; + while (__secondChild < (__len - 1) / 2) + { + __secondChild = 2 * (__secondChild + 1); + if (__comp(*(__first + __secondChild), + *(__first + (__secondChild - 1)))) + __secondChild--; + *(__first + __holeIndex) = ranges::iter_move(__first + __secondChild); + __holeIndex = __secondChild; + } + if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2) + { + __secondChild = 2 * (__secondChild + 1); + *(__first + __holeIndex) = ranges::iter_move(__first + (__secondChild - 1)); + __holeIndex = __secondChild - 1; + } + __detail::__push_heap(__first, __holeIndex, __topIndex, + std::move(__value), __comp); + } + + template<typename _Iter, typename _Comp> + constexpr void + __pop_heap(_Iter __first, _Iter __last, _Iter __result, _Comp __comp) + { + iter_value_t<_Iter> __value = ranges::iter_move(__result); + *__result = ranges::iter_move(__first); + __detail::__adjust_heap(__first, 0, __last - __first, + std::move(__value), __comp); + } + } // namespace __detail + struct __pop_heap_fn { template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent, @@ -1667,10 +2146,19 @@ namespace ranges operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { - auto __lasti = ranges::next(__first, __last); - std::pop_heap(__first, __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; + if constexpr (!same_as<_Iter, _Sent>) + return (*this)(__first, ranges::next(__first, __last), + std::move(__comp), std::move(__proj)); + else + { + if (__last - __first > 1) + { + auto __back = ranges::prev(__last); + auto __comp_proj = __detail::__make_comp_proj(__comp, __proj); + __detail::__pop_heap(__first, __back, __back, __comp_proj); + } + return __last; + } } template<random_access_range _Range, @@ -1695,10 +2183,29 @@ namespace ranges operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { - auto __lasti = ranges::next(__first, __last); - std::make_heap(__first, __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; + if constexpr (!same_as<_Iter, _Sent>) + return (*this)(__first, ranges::next(__first, __last), + std::move(__comp), std::move(__proj)); + else + { + const auto __len = __last - __first; + if (__len < 2) + return __last; + + auto __comp_proj = __detail::__make_comp_proj(__comp, __proj); + auto __parent = (__len - 2) / 2; + while (true) + { + iter_value_t<_Iter> __value = ranges::iter_move(__first + __parent); + __detail::__adjust_heap(__first, __parent, __len, + std::move(__value), + __comp_proj); + if (__parent == 0) + break; + __parent--; + } + return __last; + } } template<random_access_range _Range, @@ -1723,10 +2230,20 @@ namespace ranges operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { - auto __lasti = ranges::next(__first, __last); - std::sort_heap(__first, __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; + if constexpr (!same_as<_Iter, _Sent>) + return (*this)(__first, ranges::next(__first, __last), + std::move(__comp), std::move(__proj)); + else + { + auto __comp_proj = __detail::__make_comp_proj(__comp, __proj); + _Iter __ret = __last; + while (__last - __first > 1) + { + --__last; + __detail::__pop_heap(__first, __last, __last, __comp_proj); + } + return __ret; + } } template<random_access_range _Range, @@ -1809,6 +2326,157 @@ namespace ranges inline constexpr __is_heap_fn is_heap{}; + namespace __detail + { + template<typename _Iter, typename _Comp> + constexpr void + __move_median_to_first(_Iter __result, _Iter __a, _Iter __b, _Iter __c, + _Comp __comp) + { + if (__comp(*__a, *__b)) + { + if (__comp(*__b, *__c)) + ranges::iter_swap(__result, __b); + else if (__comp(*__a, *__c)) + ranges::iter_swap(__result, __c); + else + ranges::iter_swap(__result, __a); + } + else if (__comp(*__a, *__c)) + ranges::iter_swap(__result, __a); + else if (__comp(*__b, *__c)) + ranges::iter_swap(__result, __c); + else + ranges::iter_swap(__result, __b); + } + + template<typename _Iter, typename _Comp> + constexpr void + __unguarded_linear_insert(_Iter __last, _Comp __comp) + { + iter_value_t<_Iter> __val = ranges::iter_move(__last); + _Iter __next = __last; + --__next; + while (__comp(__val, *__next)) + { + *__last = ranges::iter_move(__next); + __last = __next; + --__next; + } + *__last = std::move(__val); + } + + template<typename _Iter, typename _Comp> + constexpr void + __insertion_sort(_Iter __first, _Iter __last, _Comp __comp) + { + if (__first == __last) + return; + + for (_Iter __i = ranges::next(__first); __i != __last; ++__i) + { + if (__comp(*__i, *__first)) + { + iter_value_t<_Iter> __val = ranges::iter_move(__i); + ranges::move_backward(__first, __i, ranges::next(__i)); + *__first = std::move(__val); + } + else + __detail::__unguarded_linear_insert(__i, __comp); + } + } + + template<typename _Iter, typename _Comp> + constexpr void + __unguarded_insertion_sort(_Iter __first, _Iter __last, _Comp __comp) + { + for (_Iter __i = __first; __i != __last; ++__i) + __detail::__unguarded_linear_insert(__i, __comp); + } + + inline constexpr int __sort_threshold = 16; + + template<typename _Iter, typename _Comp> + constexpr void + __final_insertion_sort(_Iter __first, _Iter __last, _Comp __comp) + { + constexpr iter_difference_t<_Iter> __threshold = __sort_threshold; + if (__last - __first > __threshold) + { + __detail::__insertion_sort(__first, __first + __threshold, __comp); + __detail::__unguarded_insertion_sort(__first + __threshold, __last, + __comp); + } + else + __detail::__insertion_sort(__first, __last, __comp); + } + + template<typename _Iter, typename _Comp> + constexpr _Iter + __unguarded_partition(_Iter __first, _Iter __last, _Iter __pivot, _Comp __comp) + { + while (true) + { + while (__comp(*__first, *__pivot)) + ++__first; + --__last; + while (__comp(*__pivot, *__last)) + --__last; + if (!(__first < __last)) + return __first; + ranges::iter_swap(__first, __last); + ++__first; + } + } + + template<typename _Iter, typename _Comp> + constexpr _Iter + __unguarded_partition_pivot(_Iter __first, _Iter __last, _Comp __comp) + { + _Iter __mid = __first + (__last - __first) / 2; + __detail::__move_median_to_first(__first, ranges::next(__first), __mid, + ranges::prev(__last), __comp); + return __detail::__unguarded_partition(ranges::next(__first), __last, + __first, __comp); + } + + template<typename _Iter, typename _Comp> + constexpr void + __heap_select(_Iter __first, _Iter __middle, _Iter __last, _Comp __comp) + { + ranges::make_heap(__first, __middle, __comp); + for (_Iter __i = __middle; __i < __last; ++__i) + if (__comp(*__i, *__first)) + __detail::__pop_heap(__first, __middle, __i, __comp); + } + + template<typename _Iter, typename _Comp> + constexpr void + __partial_sort(_Iter __first, _Iter __middle, _Iter __last, _Comp __comp) + { + __detail::__heap_select(__first, __middle, __last, __comp); + ranges::sort_heap(__first, __middle, __comp); + } + + template<typename _Iter, typename _Comp> + constexpr void + __introsort_loop(_Iter __first, _Iter __last, unsigned __depth_limit, _Comp __comp) + { + while (__last - __first > __sort_threshold) + { + if (__depth_limit == 0) + { + __detail::__partial_sort(__first, __last, __last, __comp); + return; + } + --__depth_limit; + _Iter __cut = __detail::__unguarded_partition_pivot(__first, __last, __comp); + __detail::__introsort_loop(__cut, __last, __depth_limit, __comp); + __last = __cut; + } + } + } // namespace __detail + struct __sort_fn { template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent, @@ -1818,10 +2486,21 @@ namespace ranges operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { - auto __lasti = ranges::next(__first, __last); - _GLIBCXX_STD_A::sort(std::move(__first), __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; + if constexpr (!same_as<_Iter, _Sent>) + return (*this)(__first, ranges::next(__first, __last), + std::move(__comp), std::move(__proj)); + else + { + if (__first != __last) + { + auto __comp_proj = __detail::__make_comp_proj(__comp, __proj); + auto __n = __detail::__to_unsigned_like(__last - __first); + unsigned __depth_limit = (std::__bit_width(__n) - 1) * 2; + __detail::__introsort_loop(__first, __last, __depth_limit, __comp_proj); + __detail::__final_insertion_sort(__first, __last, __comp_proj); + } + return __last; + } } template<random_access_range _Range, @@ -1837,6 +2516,169 @@ namespace ranges inline constexpr __sort_fn sort{}; + namespace __detail + { + // This is a helper function for the __merge_sort_loop routines. + template<typename _Iter, typename _Out, typename _Comp> + _Out + __move_merge(_Iter __first1, _Iter __last1, + _Iter __first2, _Iter __last2, + _Out __result, _Comp __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(*__first2, *__first1)) + { + *__result = ranges::iter_move(__first2); + ++__first2; + } + else + { + *__result = ranges::iter_move(__first1); + ++__first1; + } + ++__result; + } + return ranges::move(__first2, __last2, + ranges::move(__first1, __last1, __result).out).out; + } + + template<typename _Iter, typename _Out, typename _Distance, typename _Comp> + void + __merge_sort_loop(_Iter __first, _Iter __last, _Out __result, + _Distance __step_size, _Comp __comp) + { + const _Distance __two_step = 2 * __step_size; + + while (__last - __first >= __two_step) + { + __result = __detail::__move_merge(__first, __first + __step_size, + __first + __step_size, + __first + __two_step, + __result, __comp); + __first += __two_step; + } + __step_size = ranges::min(_Distance(__last - __first), __step_size); + + __detail::__move_merge(__first, __first + __step_size, + __first + __step_size, __last, __result, __comp); + } + + template<typename _Iter, typename _Distance, typename _Compare> + constexpr void + __chunk_insertion_sort(_Iter __first, _Iter __last, + _Distance __chunk_size, _Compare __comp) + { + while (__last - __first >= __chunk_size) + { + __detail::__insertion_sort(__first, __first + __chunk_size, __comp); + __first += __chunk_size; + } + __detail::__insertion_sort(__first, __last, __comp); + } + + template<typename _Iter, typename _Pointer, typename _Comp> + void + __merge_sort_with_buffer(_Iter __first, _Iter __last, + _Pointer __buffer, _Comp __comp) + { + using _Distance = iter_difference_t<_Iter>; + + const _Distance __len = __last - __first; + const _Pointer __buffer_last = __buffer + ptrdiff_t(__len); + + constexpr int __chunk_size = 7; + _Distance __step_size = __chunk_size; + __detail::__chunk_insertion_sort(__first, __last, __step_size, __comp); + + while (__step_size < __len) + { + __detail::__merge_sort_loop(__first, __last, __buffer, + __step_size, __comp); + __step_size *= 2; + __detail::__merge_sort_loop(__buffer, __buffer_last, __first, + ptrdiff_t(__step_size), __comp); + __step_size *= 2; + } + } + + template<typename _Iter, typename _Pointer, typename _Comp> + void + __merge_adaptive(_Iter __first, _Iter __middle, _Iter __last, + iter_difference_t<_Iter> __len1, + iter_difference_t<_Iter> __len2, + _Pointer __buffer, _Comp __comp); // defined near inplace_merge + + template<typename _Iter, typename _Distance, typename _Pointer, typename _Comp> + void + __merge_adaptive_resize(_Iter __first, _Iter __middle, _Iter __last, + _Distance __len1, _Distance __len2, + _Pointer __buffer, _Distance __buffer_size, + _Comp __comp); // defined near inplace_merge + + template<typename _Iter, typename _Distance, typename _Comp> + constexpr void + __merge_without_buffer(_Iter __first, _Iter __middle, _Iter __last, + _Distance __len1, _Distance __len2, + _Comp __comp); // defined near inplace_merge + + template<typename _Iter, typename _Pointer, typename _Comp> + void + __stable_sort_adaptive(_Iter __first, _Iter __middle, _Iter __last, + _Pointer __buffer, _Comp __comp) + { + __detail::__merge_sort_with_buffer(__first, __middle, __buffer, __comp); + __detail::__merge_sort_with_buffer(__middle, __last, __buffer, __comp); + + __detail::__merge_adaptive(__first, __middle, __last, + __middle - __first, __last - __middle, + __buffer, __comp); + } + + template<typename _Iter, typename _Pointer, typename _Distance, typename _Comp> + void + __stable_sort_adaptive_resize(_Iter __first, _Iter __last, + _Pointer __buffer, _Distance __buffer_size, + _Comp __comp) + { + const _Distance __len = (__last - __first + 1) / 2; + const _Iter __middle = __first + __len; + if (__len > __buffer_size) + { + __detail::__stable_sort_adaptive_resize(__first, __middle, __buffer, + __buffer_size, __comp); + __detail::__stable_sort_adaptive_resize(__middle, __last, __buffer, + __buffer_size, __comp); + __detail::__merge_adaptive_resize(__first, __middle, __last, + _Distance(__middle - __first), + _Distance(__last - __middle), + __buffer, __buffer_size, + __comp); + } + else + __detail::__stable_sort_adaptive(__first, __middle, __last, + __buffer, __comp); + } + + template<typename _Iter, typename _Comp> + constexpr void + __inplace_stable_sort(_Iter __first, _Iter __last, _Comp __comp) + { + if (__last - __first < 15) + { + __detail::__insertion_sort(__first, __last, __comp); + return; + } + _Iter __middle = __first + (__last - __first) / 2; + __detail::__inplace_stable_sort(__first, __middle, __comp); + __detail::__inplace_stable_sort(__middle, __last, __comp); + __detail::__merge_without_buffer(__first, __middle, __last, + __middle - __first, + __last - __middle, + __comp); + } + } // namespace __detail + struct __stable_sort_fn { template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent, @@ -1847,10 +2689,46 @@ namespace ranges operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { - auto __lasti = ranges::next(__first, __last); - std::stable_sort(std::move(__first), __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; + if constexpr (!same_as<_Iter, _Sent>) + return (*this)(__first, ranges::next(__first, __last), + std::move(__comp), std::move(__proj)); + else + { + using _DistanceType = iter_difference_t<_Iter>; + + if (__first == __last) + return __last; + + auto __comp_proj = __detail::__make_comp_proj(__comp, __proj); + +#if _GLIBCXX_HOSTED +# if __glibcxx_constexpr_algorithms >= 202306L // >= C++26 + if consteval { + __detail::__inplace_stable_sort(__first, __last, __comp_proj); + return __last; + } +# endif + + typedef _Temporary_buffer<_Iter, iter_value_t<_Iter>> _TmpBuf; + // __stable_sort_adaptive sorts the range in two halves, + // so the buffer only needs to fit half the range at once. + _TmpBuf __buf(__first, ptrdiff_t((__last - __first + 1) / 2)); + + if (__buf._M_requested_size() == __buf.size()) [[likely]] + __detail::__stable_sort_adaptive(__first, + __first + _DistanceType(__buf.size()), + __last, __buf.begin(), __comp_proj); + else if (__buf.begin()) [[unlikely]] + __detail::__inplace_stable_sort(__first, __last, __comp_proj); + else + __detail::__stable_sort_adaptive_resize(__first, __last, __buf.begin(), + _DistanceType(__buf.size()), + __comp_proj); +#else + __detail::__inplace_stable_sort(__first, __last, __comp_proj); +#endif + return __last; + } } template<random_access_range _Range, @@ -1887,7 +2765,7 @@ namespace ranges std::__invoke(__proj, *__first))) { ranges::pop_heap(__first, __middle, __comp, __proj); - ranges::iter_swap(__middle-1, __i); + ranges::iter_swap(std::prev(__middle), __i); ranges::push_heap(__first, __middle, __comp, __proj); } ranges::sort_heap(__first, __middle, __comp, __proj); @@ -1954,7 +2832,7 @@ namespace ranges { ranges::pop_heap(__result_first, __result_real_last, __comp, __proj2); - *(__result_real_last-1) = *__first; + *ranges::prev(__result_real_last) = *__first; ranges::push_heap(__result_first, __result_real_last, __comp, __proj2); } @@ -1991,7 +2869,7 @@ namespace ranges typename _Proj = identity, indirect_strict_weak_order<projected<_Iter, _Proj>> _Comp = ranges::less> - constexpr _Iter + [[nodiscard]] constexpr _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { @@ -2010,7 +2888,7 @@ namespace ranges template<forward_range _Range, typename _Proj = identity, indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - constexpr borrowed_iterator_t<_Range> + [[nodiscard]] constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -2026,7 +2904,7 @@ namespace ranges typename _Proj = identity, indirect_strict_weak_order<projected<_Iter, _Proj>> _Comp = ranges::less> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { @@ -2045,7 +2923,7 @@ namespace ranges template<forward_range _Range, typename _Proj = identity, indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -2055,6 +2933,34 @@ namespace ranges inline constexpr __is_sorted_fn is_sorted{}; + namespace __detail + { + template<typename _Iter, typename _Comp> + constexpr void + __introselect(_Iter __first, _Iter __nth, _Iter __last, + iter_difference_t<_Iter> __depth_limit, _Comp __comp) + { + while (__last - __first > 3) + { + if (__depth_limit == 0) + { + __detail::__heap_select(__first, ranges::next(__nth), __last, + __comp); + // Place the nth largest element in its final position. + ranges::iter_swap(__first, __nth); + return; + } + --__depth_limit; + _Iter __cut = __detail::__unguarded_partition_pivot(__first, __last, __comp); + if (__cut <= __nth) + __first = __cut; + else + __last = __cut; + } + __detail::__insertion_sort(__first, __last, __comp); + } + } // namespace __detail + struct __nth_element_fn { template<random_access_iterator _Iter, sentinel_for<_Iter> _Sent, @@ -2064,11 +2970,21 @@ namespace ranges operator()(_Iter __first, _Iter __nth, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { - auto __lasti = ranges::next(__first, __last); - _GLIBCXX_STD_A::nth_element(std::move(__first), std::move(__nth), - __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; + if constexpr (!same_as<_Iter, _Sent>) + return (*this)(__first, __nth, ranges::next(__first, __last), + std::move(__comp), std::move(__proj)); + else + { + if (__first == __last || __nth == __last) + return __last; + + auto __comp_proj = __detail::__make_comp_proj(__comp, __proj); + auto __n = __detail::__to_unsigned_like(__last - __first); + __detail::__introselect(__first, __nth, __last, + std::__bit_width(__n) * 2, + __comp_proj); + return __last; + } } template<random_access_range _Range, @@ -2092,7 +3008,7 @@ namespace ranges typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj), indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>> _Comp = ranges::less> - constexpr _Iter + [[nodiscard]] constexpr _Iter operator()(_Iter __first, _Sent __last, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { @@ -2122,7 +3038,7 @@ namespace ranges indirect_strict_weak_order<const _Tp*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - constexpr borrowed_iterator_t<_Range> + [[nodiscard]] constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { @@ -2140,7 +3056,7 @@ namespace ranges typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj), indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>> _Comp = ranges::less> - constexpr _Iter + [[nodiscard]] constexpr _Iter operator()(_Iter __first, _Sent __last, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { @@ -2170,7 +3086,7 @@ namespace ranges indirect_strict_weak_order<const _Tp*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - constexpr borrowed_iterator_t<_Range> + [[nodiscard]] constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { @@ -2188,7 +3104,7 @@ namespace ranges typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj), indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>> _Comp = ranges::less> - constexpr subrange<_Iter> + [[nodiscard]] constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { @@ -2233,7 +3149,7 @@ namespace ranges indirect_strict_weak_order<const _Tp*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - constexpr borrowed_subrange_t<_Range> + [[nodiscard]] constexpr borrowed_subrange_t<_Range> operator()(_Range&& __r, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { @@ -2251,7 +3167,7 @@ namespace ranges typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj), indirect_strict_weak_order<const _Tp*, projected<_Iter, _Proj>> _Comp = ranges::less> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Iter __first, _Sent __last, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { @@ -2269,7 +3185,7 @@ namespace ranges indirect_strict_weak_order<const _Tp*, projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Range&& __r, const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const { @@ -2285,7 +3201,7 @@ namespace ranges template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { @@ -2301,7 +3217,7 @@ namespace ranges template<input_range _Range, typename _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -2383,6 +3299,80 @@ namespace ranges inline constexpr __partition_fn partition{}; #if _GLIBCXX_HOSTED + namespace __detail + { + // Like find_if_not(), but uses and updates a count of the + // remaining range length instead of comparing against an end + // iterator. + template<typename _Iter, typename _Pred, typename _Distance> + constexpr _Iter + __find_if_not_n(_Iter __first, _Distance& __len, _Pred __pred) + { + for (; __len; --__len, (void) ++__first) + if (!__pred(*__first)) + break; + return __first; + } + + template<typename _Iter, typename _Sent, typename _Pointer, + typename _Pred, typename _Distance> + constexpr subrange<_Iter> + __stable_partition_adaptive(_Iter __first, _Sent __last, + _Pred __pred, _Distance __len, + _Pointer __buffer, + _Distance __buffer_size) + { + if (__len == 1) + return {__first, ranges::next(__first, 1)}; + + if (__len <= __buffer_size) + { + _Iter __result1 = __first; + _Pointer __result2 = __buffer; + + // The precondition guarantees that !__pred(__first), so + // move that element to the buffer before starting the loop. + // This ensures that we only call __pred once per element. + *__result2 = ranges::iter_move(__first); + ++__result2; + ++__first; + for (; __first != __last; ++__first) + if (__pred(*__first)) + { + *__result1 = ranges::iter_move(__first); + ++__result1; + } + else + { + *__result2 = ranges::iter_move(__first); + ++__result2; + } + + ranges::move(__buffer, __result2, __result1); + return {__result1, __first}; + } + + _Iter __middle = __first; + ranges::advance(__middle, __len / 2); + _Iter __left_split + = __detail::__stable_partition_adaptive(__first, __middle, __pred, + __len / 2, __buffer, + __buffer_size).begin(); + + // Advance past true-predicate values to satisfy this + // function's preconditions. + _Distance __right_len = __len - __len / 2; + _Iter __right_split = __detail::__find_if_not_n(__middle, __right_len, __pred); + + if (__right_len) + __right_split + = __detail::__stable_partition_adaptive(__right_split, __last, __pred, + __right_len, __buffer, __buffer_size).begin(); + + return ranges::rotate(__left_split, __middle, __right_split); + } + } // namespace __detail + struct __stable_partition_fn { template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, @@ -2394,11 +3384,33 @@ namespace ranges operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { - auto __lasti = ranges::next(__first, __last); - auto __middle - = std::stable_partition(std::move(__first), __lasti, - __detail::__make_pred_proj(__pred, __proj)); - return {std::move(__middle), std::move(__lasti)}; + __first = ranges::find_if_not(__first, __last, __pred, __proj); + + if (__first == __last) + return {__first, __first}; + + using _DistanceType = iter_difference_t<_Iter>; + const _DistanceType __len = ranges::distance(__first, __last); + + auto __pred_proj = __detail::__make_pred_proj(__pred, __proj); + +#if __glibcxx_constexpr_algorithms >= 202306L // >= C++26 + if consteval { + // Simulate a _Temporary_buffer of length 1: + iter_value_t<_Iter> __buf = ranges::iter_move(__first); + *__first = std::move(__buf); + return __detail::__stable_partition_adaptive(__first, __last, + __pred_proj, + __len, &__buf, + _DistanceType(1)); + } +#endif + + _Temporary_buffer<_Iter, iter_value_t<_Iter>> __buf(__first, ptrdiff_t(__len)); + return __detail::__stable_partition_adaptive(__first, __last, + __pred_proj, + __len, __buf.begin(), + _DistanceType(__buf.size())); } template<bidirectional_range _Range, typename _Proj = identity, @@ -2497,7 +3509,7 @@ namespace ranges template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - constexpr _Iter + [[nodiscard]] constexpr _Iter operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { @@ -2523,7 +3535,7 @@ namespace ranges template<forward_range _Range, typename _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - constexpr borrowed_iterator_t<_Range> + [[nodiscard]] constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -2594,6 +3606,215 @@ namespace ranges inline constexpr __merge_fn merge{}; + namespace __detail + { + template<typename _Iter1, typename _Iter2, typename _Out, typename _Comp> + void + __move_merge_adaptive(_Iter1 __first1, _Iter1 __last1, + _Iter2 __first2, _Iter2 __last2, + _Out __result, _Comp __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(*__first2, *__first1)) + { + *__result = ranges::iter_move(__first2); + ++__first2; + } + else + { + *__result = ranges::iter_move(__first1); + ++__first1; + } + ++__result; + } + if (__first1 != __last1) + ranges::move(__first1, __last1, __result); + } + + template<typename _Iter1, typename _Iter2, typename _Iter3, typename _Comp> + void + __move_merge_adaptive_backward(_Iter1 __first1, _Iter1 __last1, + _Iter2 __first2, _Iter2 __last2, + _Iter3 __result, _Comp __comp) + { + if (__first1 == __last1) + { + ranges::move_backward(__first2, __last2, __result); + return; + } + else if (__first2 == __last2) + return; + + --__last1; + --__last2; + while (true) + { + if (__comp(*__last2, *__last1)) + { + *--__result = ranges::iter_move(__last1); + if (__first1 == __last1) + { + ranges::move_backward(__first2, ++__last2, __result); + return; + } + --__last1; + } + else + { + *--__result = ranges::iter_move(__last2); + if (__first2 == __last2) + return; + --__last2; + } + } + } + + template<typename _Iter1, typename _Iter2> + _Iter1 + __rotate_adaptive(_Iter1 __first, _Iter1 __middle, _Iter1 __last, + iter_difference_t<_Iter1> __len1, + iter_difference_t<_Iter1> __len2, + _Iter2 __buffer, + iter_difference_t<_Iter1> __buffer_size) + { + _Iter2 __buffer_end; + if (__len1 > __len2 && __len2 <= __buffer_size) + { + if (__len2) + { + __buffer_end = ranges::move(__middle, __last, __buffer).out; + ranges::move_backward(__first, __middle, __last); + return ranges::move(__buffer, __buffer_end, __first).out; + } + else + return __first; + } + else if (__len1 <= __buffer_size) + { + if (__len1) + { + __buffer_end = ranges::move(__first, __middle, __buffer).out; + ranges::move(__middle, __last, __first); + return ranges::move_backward(__buffer, __buffer_end, __last).out; + } + else + return __last; + } + else + return ranges::rotate(__first, __middle, __last).begin(); + } + + template<typename _Iter, typename _Pointer, typename _Comp> + void + __merge_adaptive(_Iter __first, _Iter __middle, _Iter __last, + iter_difference_t<_Iter> __len1, + iter_difference_t<_Iter> __len2, + _Pointer __buffer, _Comp __comp) + { + if (__len1 <= __len2) + { + _Pointer __buffer_end = ranges::move(__first, __middle, __buffer).out; + __detail::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last, + __first, __comp); + } + else + { + _Pointer __buffer_end = ranges::move(__middle, __last, __buffer).out; + __detail::__move_merge_adaptive_backward(__first, __middle, __buffer, + __buffer_end, __last, __comp); + } + } + + template<typename _Iter, typename _Distance, typename _Pointer, typename _Comp> + void + __merge_adaptive_resize(_Iter __first, _Iter __middle, _Iter __last, + _Distance __len1, _Distance __len2, + _Pointer __buffer, _Distance __buffer_size, + _Comp __comp) + { + if (__len1 <= __buffer_size || __len2 <= __buffer_size) + __detail::__merge_adaptive(__first, __middle, __last, + __len1, __len2, __buffer, __comp); + else + { + _Iter __first_cut = __first; + _Iter __second_cut = __middle; + _Distance __len11 = 0; + _Distance __len22 = 0; + if (__len1 > __len2) + { + __len11 = __len1 / 2; + ranges::advance(__first_cut, __len11); + __second_cut = ranges::lower_bound(__middle, __last, *__first_cut, + __comp); + __len22 = ranges::distance(__middle, __second_cut); + } + else + { + __len22 = __len2 / 2; + ranges::advance(__second_cut, __len22); + __first_cut = ranges::upper_bound(__first, __middle, *__second_cut, + __comp); + __len11 = ranges::distance(__first, __first_cut); + } + + _Iter __new_middle + = __detail::__rotate_adaptive(__first_cut, __middle, __second_cut, + _Distance(__len1 - __len11), __len22, + __buffer, __buffer_size); + __detail::__merge_adaptive_resize(__first, __first_cut, __new_middle, + __len11, __len22, + __buffer, __buffer_size, __comp); + __detail::__merge_adaptive_resize(__new_middle, __second_cut, __last, + _Distance(__len1 - __len11), + _Distance(__len2 - __len22), + __buffer, __buffer_size, __comp); + } + } + + template<typename _Iter, typename _Distance, typename _Comp> + constexpr void + __merge_without_buffer(_Iter __first, _Iter __middle, _Iter __last, + _Distance __len1, _Distance __len2, _Comp __comp) + { + if (__len1 == 0 || __len2 == 0) + return; + + if (__len1 + __len2 == 2) + { + if (__comp(*__middle, *__first)) + ranges::iter_swap(__first, __middle); + return; + } + + _Iter __first_cut = __first; + _Iter __second_cut = __middle; + _Distance __len11 = 0; + _Distance __len22 = 0; + if (__len1 > __len2) + { + __len11 = __len1 / 2; + ranges::advance(__first_cut, __len11); + __second_cut = ranges::lower_bound(__middle, __last, *__first_cut, __comp); + __len22 = ranges::distance(__middle, __second_cut); + } + else + { + __len22 = __len2 / 2; + ranges::advance(__second_cut, __len22); + __first_cut = ranges::upper_bound(__first, __middle, *__second_cut, __comp); + __len11 = ranges::distance(__first, __first_cut); + } + + _Iter __new_middle = ranges::rotate(__first_cut, __middle, __second_cut).begin(); + __detail::__merge_without_buffer(__first, __first_cut, __new_middle, + __len11, __len22, __comp); + __detail::__merge_without_buffer(__new_middle, __second_cut, __last, + __len1 - __len11, __len2 - __len22, __comp); + } + } // namespace __detail + struct __inplace_merge_fn { template<bidirectional_iterator _Iter, sentinel_for<_Iter> _Sent, @@ -2605,10 +3826,50 @@ namespace ranges operator()(_Iter __first, _Iter __middle, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { - auto __lasti = ranges::next(__first, __last); - std::inplace_merge(std::move(__first), std::move(__middle), __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; + if constexpr (!same_as<_Iter, _Sent>) + return (*this)(__first, __middle, ranges::next(__middle, __last), + std::move(__comp), std::move(__proj)); + else + { + using _DistanceType = iter_difference_t<_Iter>; + + if (__first == __middle || __middle == __last) + return __last; + + const _DistanceType __len1 = ranges::distance(__first, __middle); + const _DistanceType __len2 = ranges::distance(__middle, __last); + + auto __comp_proj = __detail::__make_comp_proj(__comp, __proj); + +#if _GLIBCXX_HOSTED +# if __glibcxx_constexpr_algorithms >= 202306L // >= C++26 + if consteval { + __detail::__merge_without_buffer(__first, __middle, __last, + __len1, __len2, __comp_proj); + return __last; + } +# endif + using _TmpBuf = _Temporary_buffer<_Iter, iter_value_t<_Iter>>; + // __merge_adaptive will use a buffer for the smaller of + // [first,middle) and [middle,last). + _TmpBuf __buf(__first, ptrdiff_t(ranges::min(__len1, __len2))); + + if (__buf.size() == __buf._M_requested_size()) [[likely]] + __detail::__merge_adaptive + (__first, __middle, __last, __len1, __len2, __buf.begin(), __comp_proj); + else if (__buf.begin() == 0) [[unlikely]] + __detail::__merge_without_buffer + (__first, __middle, __last, __len1, __len2, __comp_proj); + else + __detail::__merge_adaptive_resize + (__first, __middle, __last, __len1, __len2, __buf.begin(), + _DistanceType(__buf.size()), __comp_proj); +#else + __detail::__merge_without_buffer + (__first, __middle, __last, __len1, __len2, __comp_proj); +#endif + return __last; + } } template<bidirectional_range _Range, @@ -2635,7 +3896,7 @@ namespace ranges indirect_strict_weak_order<projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>> _Comp = ranges::less> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Comp __comp = {}, @@ -2664,7 +3925,7 @@ namespace ranges indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>, projected<iterator_t<_Range2>, _Proj2>> _Comp = ranges::less> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { @@ -2935,7 +4196,7 @@ namespace ranges template<typename _Tp, typename _Proj = identity, indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less> - constexpr const _Tp& + [[nodiscard]] constexpr const _Tp& operator()(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) const { @@ -2952,13 +4213,13 @@ namespace ranges _Comp = ranges::less> requires indirectly_copyable_storable<iterator_t<_Range>, range_value_t<_Range>*> - constexpr range_value_t<_Range> + [[nodiscard]] constexpr range_value_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); auto __last = ranges::end(__r); __glibcxx_assert(__first != __last); - auto __result = *__first; + range_value_t<_Range> __result(*__first); while (++__first != __last) { auto&& __tmp = *__first; @@ -2973,7 +4234,7 @@ namespace ranges template<copyable _Tp, typename _Proj = identity, indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less> - constexpr _Tp + [[nodiscard]] constexpr _Tp operator()(initializer_list<_Tp> __r, _Comp __comp = {}, _Proj __proj = {}) const { @@ -2989,7 +4250,7 @@ namespace ranges template<typename _Tp, typename _Proj = identity, indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less> - constexpr const _Tp& + [[nodiscard]] constexpr const _Tp& operator()(const _Tp& __val, const _Tp& __lo, const _Tp& __hi, _Comp __comp = {}, _Proj __proj = {}) const { @@ -3039,7 +4300,7 @@ namespace ranges template<typename _Tp, typename _Proj = identity, indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less> - constexpr minmax_result<const _Tp&> + [[nodiscard]] constexpr minmax_result<const _Tp&> operator()(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) const { @@ -3055,7 +4316,7 @@ namespace ranges indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> requires indirectly_copyable_storable<iterator_t<_Range>, range_value_t<_Range>*> - constexpr minmax_result<range_value_t<_Range>> + [[nodiscard]] constexpr minmax_result<range_value_t<_Range>> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); @@ -3114,7 +4375,7 @@ namespace ranges template<copyable _Tp, typename _Proj = identity, indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less> - constexpr minmax_result<_Tp> + [[nodiscard]] constexpr minmax_result<_Tp> operator()(initializer_list<_Tp> __r, _Comp __comp = {}, _Proj __proj = {}) const { @@ -3131,7 +4392,7 @@ namespace ranges typename _Proj = identity, indirect_strict_weak_order<projected<_Iter, _Proj>> _Comp = ranges::less> - constexpr _Iter + [[nodiscard]] constexpr _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { @@ -3152,7 +4413,7 @@ namespace ranges template<forward_range _Range, typename _Proj = identity, indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - constexpr borrowed_iterator_t<_Range> + [[nodiscard]] constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -3168,7 +4429,7 @@ namespace ranges typename _Proj = identity, indirect_strict_weak_order<projected<_Iter, _Proj>> _Comp = ranges::less> - constexpr _Iter + [[nodiscard]] constexpr _Iter operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { @@ -3189,7 +4450,7 @@ namespace ranges template<forward_range _Range, typename _Proj = identity, indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - constexpr borrowed_iterator_t<_Range> + [[nodiscard]] constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -3208,7 +4469,7 @@ namespace ranges typename _Proj = identity, indirect_strict_weak_order<projected<_Iter, _Proj>> _Comp = ranges::less> - constexpr minmax_element_result<_Iter> + [[nodiscard]] constexpr minmax_element_result<_Iter> operator()(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) const { @@ -3263,7 +4524,7 @@ namespace ranges template<forward_range _Range, typename _Proj = identity, indirect_strict_weak_order<projected<iterator_t<_Range>, _Proj>> _Comp = ranges::less> - constexpr minmax_element_result<borrowed_iterator_t<_Range>> + [[nodiscard]] constexpr minmax_element_result<borrowed_iterator_t<_Range>> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -3281,7 +4542,7 @@ namespace ranges indirect_strict_weak_order<projected<_Iter1, _Proj1>, projected<_Iter2, _Proj2>> _Comp = ranges::less> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Comp __comp = {}, @@ -3367,7 +4628,7 @@ namespace ranges indirect_strict_weak_order<projected<iterator_t<_Range1>, _Proj1>, projected<iterator_t<_Range2>, _Proj2>> _Comp = ranges::less> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { @@ -3596,7 +4857,7 @@ namespace ranges typename _Proj = identity, typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj)> requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Tp*> - constexpr subrange<_Iter> + [[nodiscard]] constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) const { if constexpr (same_as<_Iter, _Sent> && bidirectional_iterator<_Iter>) @@ -3629,7 +4890,7 @@ namespace ranges typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(iterator_t<_Range>, _Proj)> requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Tp*> - constexpr borrowed_subrange_t<_Range> + [[nodiscard]] constexpr borrowed_subrange_t<_Range> operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), __value, std::move(__proj)); } }; @@ -3640,7 +4901,7 @@ namespace ranges { template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - constexpr subrange<_Iter> + [[nodiscard]] constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { if constexpr (same_as<_Iter, _Sent> && bidirectional_iterator<_Iter>) @@ -3671,7 +4932,7 @@ namespace ranges template<forward_range _Range, typename _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - constexpr borrowed_subrange_t<_Range> + [[nodiscard]] constexpr borrowed_subrange_t<_Range> operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__pred), std::move(__proj)); } }; @@ -3682,7 +4943,7 @@ namespace ranges { template<forward_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - constexpr subrange<_Iter> + [[nodiscard]] constexpr subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { if constexpr (same_as<_Iter, _Sent> && bidirectional_iterator<_Iter>) @@ -3713,7 +4974,7 @@ namespace ranges template<forward_range _Range, typename _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - constexpr borrowed_subrange_t<_Range> + [[nodiscard]] constexpr borrowed_subrange_t<_Range> operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__pred), std::move(__proj)); } }; @@ -3978,6 +5239,7 @@ namespace ranges #endif // __glibcxx_ranges_fold } // namespace ranges +#if __glibcxx_shift >= 201806L // C++ >= 20 template<typename _ForwardIterator> constexpr _ForwardIterator shift_left(_ForwardIterator __first, _ForwardIterator __last, @@ -4068,6 +5330,120 @@ namespace ranges } } } +#endif + +namespace ranges +{ +#if __glibcxx_shift >= 202202L // C++ >= 23 + struct __shift_left_fn + { + template<permutable _Iter, sentinel_for<_Iter> _Sent> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __n) const + { + __glibcxx_assert(__n >= 0); + if (__n == 0) + return {__first, ranges::next(__first, __last)}; + + auto __mid = ranges::next(__first, __n, __last); + if (__mid == __last) + return {__first, __first}; + return {__first, ranges::move(__mid, __last, __first).out}; + } + + template<forward_range _Range> + requires permutable<iterator_t<_Range>> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, range_difference_t<_Range> __n) const + { return (*this)(ranges::begin(__r), ranges::end(__r), __n); } + }; + + inline constexpr __shift_left_fn shift_left{}; + + struct __shift_right_fn + { + template<permutable _Iter, sentinel_for<_Iter> _Sent> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __n) const + { + __glibcxx_assert(__n >= 0); + if (__n == 0) + return {__first, ranges::next(__first, __last)}; + + if constexpr (bidirectional_iterator<_Iter> && same_as<_Iter, _Sent>) + { + auto __mid = ranges::next(__last, -__n, __first); + if (__mid == __first) + return {__last, __last}; + + return {ranges::move_backward(__first, __mid, __last).out, __last}; + } + else + { + auto __result = ranges::next(__first, __n, __last); + if (__result == __last) + return {__result, __result}; + + auto __dest_head = __first, __dest_tail = __result; + while (__dest_head != __result) + { + if (__dest_tail == __last) + { + // If we get here, then we must have + // 2*n >= distance(__first, __last) + // i.e. we are shifting out at least half of the range. In + // this case we can safely perform the shift with a single + // move. + auto __lasti = ranges::move(__first, __dest_head, __result).out; + // __glibcxx_assert(__lasti == __last); + return {__result, __lasti}; + } + ++__dest_head; + ++__dest_tail; + } + + for (;;) + { + // At the start of each iteration of this outer loop, the range + // [__first, __result) contains those elements that after shifting + // the whole range right by __n, should end up in + // [__dest_head, __dest_tail) in order. + + // The below inner loop swaps the elements of [__first, __result) + // and [__dest_head, __dest_tail), while simultaneously shifting + // the latter range by __n. + auto __cursor = __first; + while (__cursor != __result) + { + if (__dest_tail == __last) + { + // At this point the ranges [__first, result) and + // [__dest_head, dest_tail) are disjoint, so we can safely + // move the remaining elements. + __dest_head = ranges::move(__cursor, __result, __dest_head).out; + auto __lasti = ranges::move(__first, __cursor, __dest_head).out; + // __glibcxx_assert(__lasti == __last); + return {__result, __lasti}; + } + ranges::iter_swap(__cursor, __dest_head); + ++__dest_head; + ++__dest_tail; + ++__cursor; + } + } + } + } + + template<forward_range _Range> + requires permutable<iterator_t<_Range>> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, range_difference_t<_Range> __n) const + { return (*this)(ranges::begin(__r), ranges::end(__r), __n); } + }; + + inline constexpr __shift_right_fn shift_right{}; +#endif // C++23 +} // namespace ranges _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h index a08f659b..45ed5b4 100644 --- a/libstdc++-v3/include/bits/ranges_algobase.h +++ b/libstdc++-v3/include/bits/ranges_algobase.h @@ -101,7 +101,7 @@ namespace ranges typename _Pred = ranges::equal_to, typename _Proj1 = identity, typename _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const @@ -168,7 +168,7 @@ namespace ranges typename _Proj1 = identity, typename _Proj2 = identity> requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - constexpr bool + [[nodiscard]] constexpr bool operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index dde1649..0b8151c 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -68,29 +68,22 @@ namespace ranges namespace __detail { + [[__gnu__::__always_inline__]] constexpr __max_size_type __to_unsigned_like(__max_size_type __t) noexcept { return __t; } + [[__gnu__::__always_inline__]] constexpr __max_size_type __to_unsigned_like(__max_diff_type __t) noexcept { return __max_size_type(__t); } template<integral _Tp> + [[__gnu__::__always_inline__]] constexpr auto __to_unsigned_like(_Tp __t) noexcept { return static_cast<make_unsigned_t<_Tp>>(__t); } -#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ - constexpr unsigned __int128 - __to_unsigned_like(__int128 __t) noexcept - { return __t; } - - constexpr unsigned __int128 - __to_unsigned_like(unsigned __int128 __t) noexcept - { return __t; } -#endif - template<typename _Tp> using __make_unsigned_like_t = decltype(__detail::__to_unsigned_like(std::declval<_Tp>())); @@ -113,23 +106,24 @@ namespace ranges { private: template<typename _Tp> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (is_array_v<remove_reference_t<_Tp>>) return true; else if constexpr (__member_begin<_Tp>) - return noexcept(__decay_copy(std::declval<_Tp&>().begin())); + return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().begin())); else - return noexcept(__decay_copy(begin(std::declval<_Tp&>()))); + return noexcept(_GLIBCXX_AUTO_CAST(begin(std::declval<_Tp&>()))); } public: template<__maybe_borrowed_range _Tp> requires is_array_v<remove_reference_t<_Tp>> || __member_begin<_Tp> || __adl_begin<_Tp> + [[nodiscard, __gnu__::__always_inline__]] constexpr auto - operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>()) + operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>()) { if constexpr (is_array_v<remove_reference_t<_Tp>>) { @@ -146,7 +140,7 @@ namespace ranges template<typename _Tp> concept __member_end = requires(_Tp& __t) { - { __decay_copy(__t.end()) } -> sentinel_for<__range_iter_t<_Tp>>; + { _GLIBCXX_AUTO_CAST(__t.end()) } -> sentinel_for<__range_iter_t<_Tp>>; }; // Poison pill so that unqualified lookup doesn't find std::end. @@ -156,30 +150,31 @@ namespace ranges concept __adl_end = __class_or_enum<remove_reference_t<_Tp>> && requires(_Tp& __t) { - { __decay_copy(end(__t)) } -> sentinel_for<__range_iter_t<_Tp>>; + { _GLIBCXX_AUTO_CAST(end(__t)) } -> sentinel_for<__range_iter_t<_Tp>>; }; struct _End { private: template<typename _Tp> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>) return true; else if constexpr (__member_end<_Tp>) - return noexcept(__decay_copy(std::declval<_Tp&>().end())); + return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().end())); else - return noexcept(__decay_copy(end(std::declval<_Tp&>()))); + return noexcept(_GLIBCXX_AUTO_CAST(end(std::declval<_Tp&>()))); } public: template<__maybe_borrowed_range _Tp> requires is_bounded_array_v<remove_reference_t<_Tp>> || __member_end<_Tp> || __adl_end<_Tp> + [[nodiscard, __gnu__::__always_inline__]] constexpr auto - operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>()) + operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>()) { if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>) { @@ -196,7 +191,7 @@ namespace ranges template<typename _Tp> concept __member_rbegin = requires(_Tp& __t) { - { __decay_copy(__t.rbegin()) } -> input_or_output_iterator; + { _GLIBCXX_AUTO_CAST(__t.rbegin()) } -> input_or_output_iterator; }; void rbegin() = delete; @@ -205,7 +200,7 @@ namespace ranges concept __adl_rbegin = __class_or_enum<remove_reference_t<_Tp>> && requires(_Tp& __t) { - { __decay_copy(rbegin(__t)) } -> input_or_output_iterator; + { _GLIBCXX_AUTO_CAST(rbegin(__t)) } -> input_or_output_iterator; }; template<typename _Tp> @@ -219,13 +214,13 @@ namespace ranges { private: template<typename _Tp> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (__member_rbegin<_Tp>) - return noexcept(__decay_copy(std::declval<_Tp&>().rbegin())); + return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().rbegin())); else if constexpr (__adl_rbegin<_Tp>) - return noexcept(__decay_copy(rbegin(std::declval<_Tp&>()))); + return noexcept(_GLIBCXX_AUTO_CAST(rbegin(std::declval<_Tp&>()))); else { if constexpr (noexcept(_End{}(std::declval<_Tp&>()))) @@ -242,8 +237,9 @@ namespace ranges public: template<__maybe_borrowed_range _Tp> requires __member_rbegin<_Tp> || __adl_rbegin<_Tp> || __reversable<_Tp> + [[nodiscard, __gnu__::__always_inline__]] constexpr auto - operator()[[nodiscard]](_Tp&& __t) const + operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>()) { if constexpr (__member_rbegin<_Tp>) @@ -258,7 +254,7 @@ namespace ranges template<typename _Tp> concept __member_rend = requires(_Tp& __t) { - { __decay_copy(__t.rend()) } + { _GLIBCXX_AUTO_CAST(__t.rend()) } -> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>; }; @@ -268,7 +264,7 @@ namespace ranges concept __adl_rend = __class_or_enum<remove_reference_t<_Tp>> && requires(_Tp& __t) { - { __decay_copy(rend(__t)) } + { _GLIBCXX_AUTO_CAST(rend(__t)) } -> sentinel_for<decltype(_RBegin{}(std::forward<_Tp>(__t)))>; }; @@ -276,13 +272,13 @@ namespace ranges { private: template<typename _Tp> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (__member_rend<_Tp>) - return noexcept(__decay_copy(std::declval<_Tp&>().rend())); + return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().rend())); else if constexpr (__adl_rend<_Tp>) - return noexcept(__decay_copy(rend(std::declval<_Tp&>()))); + return noexcept(_GLIBCXX_AUTO_CAST(rend(std::declval<_Tp&>()))); else { if constexpr (noexcept(_Begin{}(std::declval<_Tp&>()))) @@ -299,8 +295,9 @@ namespace ranges public: template<__maybe_borrowed_range _Tp> requires __member_rend<_Tp> || __adl_rend<_Tp> || __reversable<_Tp> + [[nodiscard, __gnu__::__always_inline__]] constexpr auto - operator()[[nodiscard]](_Tp&& __t) const + operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>()) { if constexpr (__member_rend<_Tp>) @@ -316,7 +313,7 @@ namespace ranges concept __member_size = !disable_sized_range<remove_cvref_t<_Tp>> && requires(_Tp& __t) { - { __decay_copy(__t.size()) } -> __detail::__is_integer_like; + { _GLIBCXX_AUTO_CAST(__t.size()) } -> __detail::__is_integer_like; }; void size() = delete; @@ -326,7 +323,7 @@ namespace ranges && !disable_sized_range<remove_cvref_t<_Tp>> && requires(_Tp& __t) { - { __decay_copy(size(__t)) } -> __detail::__is_integer_like; + { _GLIBCXX_AUTO_CAST(size(__t)) } -> __detail::__is_integer_like; }; template<typename _Tp> @@ -345,15 +342,15 @@ namespace ranges { private: template<typename _Tp> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>) return true; else if constexpr (__member_size<_Tp>) - return noexcept(__decay_copy(std::declval<_Tp&>().size())); + return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().size())); else if constexpr (__adl_size<_Tp>) - return noexcept(__decay_copy(size(std::declval<_Tp&>()))); + return noexcept(_GLIBCXX_AUTO_CAST(size(std::declval<_Tp&>()))); else if constexpr (__sentinel_size<_Tp>) return noexcept(_End{}(std::declval<_Tp&>()) - _Begin{}(std::declval<_Tp&>())); @@ -363,8 +360,9 @@ namespace ranges template<typename _Tp> requires is_bounded_array_v<remove_reference_t<_Tp>> || __member_size<_Tp> || __adl_size<_Tp> || __sentinel_size<_Tp> + [[nodiscard, __gnu__::__always_inline__]] constexpr auto - operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>()) + operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>()) { if constexpr (is_bounded_array_v<remove_reference_t<_Tp>>) return extent_v<remove_reference_t<_Tp>>; @@ -383,8 +381,9 @@ namespace ranges // 3403. Domain of ranges::ssize(E) doesn't match ranges::size(E) template<typename _Tp> requires requires (_Tp& __t) { _Size{}(__t); } + [[nodiscard, __gnu__::__always_inline__]] constexpr auto - operator()[[nodiscard]](_Tp&& __t) const noexcept(noexcept(_Size{}(__t))) + operator()(_Tp&& __t) const noexcept(noexcept(_Size{}(__t))) { auto __size = _Size{}(__t); using __size_type = decltype(__size); @@ -398,11 +397,6 @@ namespace ranges else return static_cast<make_signed_t<__size_type>>(__size); } -#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ - // For strict-ansi modes integral<__int128> is false - else if constexpr (__detail::__is_int128<__size_type>) - return static_cast<__int128>(__size); -#endif else // Must be one of __max_diff_type or __max_size_type. return __detail::__max_diff_type(__size); } @@ -428,7 +422,7 @@ namespace ranges { private: template<typename _Tp> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (__member_empty<_Tp>) @@ -444,8 +438,9 @@ namespace ranges template<typename _Tp> requires __member_empty<_Tp> || __size0_empty<_Tp> || __eq_iter_empty<_Tp> + [[nodiscard, __gnu__::__always_inline__]] constexpr bool - operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp&>()) + operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp&>()) { if constexpr (__member_empty<_Tp>) return bool(__t.empty()); @@ -463,7 +458,7 @@ namespace ranges template<typename _Tp> concept __member_data = requires(_Tp& __t) { - { __decay_copy(__t.data()) } -> __pointer_to_object; + { _GLIBCXX_AUTO_CAST(__t.data()) } -> __pointer_to_object; }; template<typename _Tp> @@ -473,11 +468,11 @@ namespace ranges { private: template<typename _Tp> - static constexpr bool + static consteval bool _S_noexcept() { if constexpr (__member_data<_Tp>) - return noexcept(__decay_copy(std::declval<_Tp&>().data())); + return noexcept(_GLIBCXX_AUTO_CAST(std::declval<_Tp&>().data())); else return noexcept(_Begin{}(std::declval<_Tp&>())); } @@ -485,8 +480,9 @@ namespace ranges public: template<__maybe_borrowed_range _Tp> requires __member_data<_Tp> || __begin_data<_Tp> + [[nodiscard, __gnu__::__always_inline__]] constexpr auto - operator()[[nodiscard]](_Tp&& __t) const noexcept(_S_noexcept<_Tp>()) + operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>()) { if constexpr (__member_data<_Tp>) return __t.data(); @@ -529,11 +525,7 @@ namespace ranges using sentinel_t = decltype(ranges::end(std::declval<_Range&>())); #if __glibcxx_ranges_as_const // >= C++23 - template<range _Range> - using const_iterator_t = const_iterator<iterator_t<_Range>>; - - template<range _Range> - using const_sentinel_t = const_sentinel<sentinel_t<_Range>>; + // const_iterator_t and const_sentinel_t defined below. template<range _Range> using range_const_reference_t = iter_const_reference_t<iterator_t<_Range>>; @@ -647,6 +639,7 @@ namespace ranges { #if __glibcxx_ranges_as_const // >= C++23 template<input_range _Range> + [[__gnu__::__always_inline__]] constexpr auto& __possibly_const_range(_Range& __r) noexcept { @@ -660,6 +653,7 @@ namespace ranges #else // If _To is an lvalue-reference, return const _Tp&, otherwise const _Tp&&. template<typename _To, typename _Tp> + [[__gnu__::__always_inline__]] constexpr decltype(auto) __as_const(_Tp& __t) noexcept { @@ -685,7 +679,7 @@ namespace ranges (ranges::begin(__access::__possibly_const_range(__t))); } { auto& __r = __access::__possibly_const_range(__t); - return const_iterator_t<decltype(__r)>(ranges::begin(__r)); + return const_iterator<decltype(ranges::begin(__r))>(ranges::begin(__r)); } #else template<typename _Tp> @@ -713,7 +707,7 @@ namespace ranges (ranges::end(__access::__possibly_const_range(__t))); } { auto& __r = __access::__possibly_const_range(__t); - return const_sentinel_t<decltype(__r)>(ranges::end(__r)); + return const_sentinel<decltype(ranges::end(__r))>(ranges::end(__r)); } #else template<typename _Tp> @@ -817,6 +811,16 @@ namespace ranges inline constexpr ranges::__access::_CData cdata{}; } +#if __glibcxx_ranges_as_const // >= C++23 + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3946. The definition of const_iterator_t should be reworked + template<range _Range> + using const_iterator_t = decltype(ranges::cbegin(std::declval<_Range&>())); + + template<range _Range> + using const_sentinel_t = decltype(ranges::cend(std::declval<_Range&>())); +#endif + namespace __detail { template<typename _Tp> @@ -894,10 +898,17 @@ namespace ranges { if constexpr (sized_sentinel_for<_Sent, _It>) { - const auto __diff = __bound - __it; + const iter_difference_t<_It> __diff = __bound - __it; if (__diff == 0) - return __n; + { + // inline any possible side effects of advance(it, bound) + if constexpr (assignable_from<_It&, _Sent>) + __it = std::move(__bound); + else if constexpr (random_access_iterator<_It>) + __it += iter_difference_t<_It>(0); + return __n; + } else if (__diff > 0 ? __n >= __diff : __n <= __diff) { (*this)(__it, __bound); @@ -912,9 +923,14 @@ namespace ranges return 0; } else - return 0; + { + // inline any possible side effects of advance(it, n) + if constexpr (random_access_iterator<_It>) + __it += iter_difference_t<_It>(0); + return 0; + } } - else if (__it == __bound || __n == 0) + else if (__n == 0 || __it == __bound) return __n; else if (__n > 0) { @@ -970,13 +986,13 @@ namespace ranges } template<typename _It, sized_sentinel_for<decay_t<_It>> _Sent> - [[nodiscard]] + [[nodiscard, __gnu__::__always_inline__]] constexpr iter_difference_t<decay_t<_It>> operator()(_It&& __first, _Sent __last) const { return __last - static_cast<const decay_t<_It>&>(__first); } template<range _Range> - [[nodiscard]] + [[nodiscard, __gnu__::__always_inline__]] constexpr range_difference_t<_Range> operator()(_Range&& __r) const { @@ -994,7 +1010,7 @@ namespace ranges struct __next_fn final { template<input_or_output_iterator _It> - [[nodiscard]] + [[nodiscard, __gnu__::__always_inline__]] constexpr _It operator()(_It __x) const { @@ -1003,7 +1019,7 @@ namespace ranges } template<input_or_output_iterator _It> - [[nodiscard]] + [[nodiscard, __gnu__::__always_inline__]] constexpr _It operator()(_It __x, iter_difference_t<_It> __n) const { @@ -1012,7 +1028,7 @@ namespace ranges } template<input_or_output_iterator _It, sentinel_for<_It> _Sent> - [[nodiscard]] + [[nodiscard, __gnu__::__always_inline__]] constexpr _It operator()(_It __x, _Sent __bound) const { @@ -1021,7 +1037,7 @@ namespace ranges } template<input_or_output_iterator _It, sentinel_for<_It> _Sent> - [[nodiscard]] + [[nodiscard, __gnu__::__always_inline__]] constexpr _It operator()(_It __x, iter_difference_t<_It> __n, _Sent __bound) const { @@ -1037,7 +1053,7 @@ namespace ranges struct __prev_fn final { template<bidirectional_iterator _It> - [[nodiscard]] + [[nodiscard, __gnu__::__always_inline__]] constexpr _It operator()(_It __x) const { @@ -1046,7 +1062,7 @@ namespace ranges } template<bidirectional_iterator _It> - [[nodiscard]] + [[nodiscard, __gnu__::__always_inline__]] constexpr _It operator()(_It __x, iter_difference_t<_It> __n) const { @@ -1055,7 +1071,7 @@ namespace ranges } template<bidirectional_iterator _It> - [[nodiscard]] + [[nodiscard, __gnu__::__always_inline__]] constexpr _It operator()(_It __x, iter_difference_t<_It> __n, _It __bound) const { diff --git a/libstdc++-v3/include/bits/ranges_cmp.h b/libstdc++-v3/include/bits/ranges_cmp.h index cd5f7b8..a53cd56 100644 --- a/libstdc++-v3/include/bits/ranges_cmp.h +++ b/libstdc++-v3/include/bits/ranges_cmp.h @@ -46,11 +46,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// [func.identity] The identity function. struct identity { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++23-extensions" // static operator() template<typename _Tp> [[nodiscard]] - constexpr _Tp&& - operator()(_Tp&& __t) const noexcept + static constexpr _Tp&& + operator()(_Tp&& __t) noexcept { return std::forward<_Tp>(__t); } +#pragma GCC diagnostic pop using is_transparent = __is_transparent; }; @@ -79,13 +82,15 @@ namespace ranges // _GLIBCXX_RESOLVE_LIB_DEFECTS // 3530 BUILTIN-PTR-MEOW should not opt the type out of syntactic checks +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++23-extensions" // static operator() /// ranges::equal_to function object type. struct equal_to { template<typename _Tp, typename _Up> requires equality_comparable_with<_Tp, _Up> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const + static constexpr bool + operator()(_Tp&& __t, _Up&& __u) noexcept(noexcept(std::declval<_Tp>() == std::declval<_Up>())) { return std::forward<_Tp>(__t) == std::forward<_Up>(__u); } @@ -97,8 +102,8 @@ namespace ranges { template<typename _Tp, typename _Up> requires equality_comparable_with<_Tp, _Up> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const + static constexpr bool + operator()(_Tp&& __t, _Up&& __u) noexcept(noexcept(std::declval<_Tp>() == std::declval<_Up>())) { return !equal_to{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } @@ -110,8 +115,8 @@ namespace ranges { template<typename _Tp, typename _Up> requires totally_ordered_with<_Tp, _Up> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const + static constexpr bool + operator()(_Tp&& __t, _Up&& __u) noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>())) { if constexpr (__detail::__less_builtin_ptr_cmp<_Tp, _Up>) @@ -137,8 +142,8 @@ namespace ranges { template<typename _Tp, typename _Up> requires totally_ordered_with<_Tp, _Up> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const + static constexpr bool + operator()(_Tp&& __t, _Up&& __u) noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>())) { return less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); } @@ -150,8 +155,8 @@ namespace ranges { template<typename _Tp, typename _Up> requires totally_ordered_with<_Tp, _Up> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const + static constexpr bool + operator()(_Tp&& __t, _Up&& __u) noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>())) { return !less{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } @@ -163,13 +168,14 @@ namespace ranges { template<typename _Tp, typename _Up> requires totally_ordered_with<_Tp, _Up> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const + static constexpr bool + operator()(_Tp&& __t, _Up&& __u) noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>())) { return !less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); } using is_transparent = __is_transparent; }; +#pragma GCC diagnostic pop } // namespace ranges #endif // __glibcxx_ranges diff --git a/libstdc++-v3/include/bits/ranges_uninitialized.h b/libstdc++-v3/include/bits/ranges_uninitialized.h index 12a714b..3f9a07f 100644 --- a/libstdc++-v3/include/bits/ranges_uninitialized.h +++ b/libstdc++-v3/include/bits/ranges_uninitialized.h @@ -556,13 +556,12 @@ namespace ranges __destroy_fn::operator()(_Iter __first, _Sent __last) const noexcept { if constexpr (is_trivially_destructible_v<iter_value_t<_Iter>>) - return ranges::next(std::move(__first), __last); - else - { - for (; __first != __last; ++__first) - ranges::destroy_at(std::__addressof(*__first)); - return __first; - } + if (!is_constant_evaluated()) + return ranges::next(std::move(__first), __last); + + for (; __first != __last; ++__first) + ranges::destroy_at(std::__addressof(*__first)); + return __first; } template<__detail::__nothrow_input_range _Range> @@ -581,13 +580,12 @@ namespace ranges operator()(_Iter __first, iter_difference_t<_Iter> __n) const noexcept { if constexpr (is_trivially_destructible_v<iter_value_t<_Iter>>) - return ranges::next(std::move(__first), __n); - else - { - for (; __n > 0; ++__first, (void)--__n) - ranges::destroy_at(std::__addressof(*__first)); - return __first; - } + if (!is_constant_evaluated()) + return ranges::next(std::move(__first), __n); + + for (; __n > 0; ++__first, (void)--__n) + ranges::destroy_at(std::__addressof(*__first)); + return __first; } }; diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h index 53b7f5c..2aa8938 100644 --- a/libstdc++-v3/include/bits/ranges_util.h +++ b/libstdc++-v3/include/bits/ranges_util.h @@ -501,7 +501,7 @@ namespace ranges typename _Tp _GLIBCXX26_RANGE_ALGO_DEF_VAL_T(_Iter, _Proj)> requires indirect_binary_predicate<ranges::equal_to, projected<_Iter, _Proj>, const _Tp*> - constexpr _Iter + [[nodiscard]] constexpr _Iter operator()(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) const { @@ -537,7 +537,7 @@ namespace ranges requires indirect_binary_predicate<ranges::equal_to, projected<iterator_t<_Range>, _Proj>, const _Tp*> - constexpr borrowed_iterator_t<_Range> + [[nodiscard]] constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -552,7 +552,7 @@ namespace ranges template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - constexpr _Iter + [[nodiscard]] constexpr _Iter operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { @@ -565,7 +565,7 @@ namespace ranges template<input_range _Range, typename _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - constexpr borrowed_iterator_t<_Range> + [[nodiscard]] constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -580,7 +580,7 @@ namespace ranges template<input_iterator _Iter, sentinel_for<_Iter> _Sent, typename _Proj = identity, indirect_unary_predicate<projected<_Iter, _Proj>> _Pred> - constexpr _Iter + [[nodiscard]] constexpr _Iter operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { @@ -593,7 +593,7 @@ namespace ranges template<input_range _Range, typename _Proj = identity, indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred> - constexpr borrowed_iterator_t<_Range> + [[nodiscard]] constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), @@ -634,7 +634,7 @@ namespace ranges typename _Pred = ranges::equal_to, typename _Proj1 = identity, typename _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - constexpr mismatch_result<_Iter1, _Iter2> + [[nodiscard]] constexpr mismatch_result<_Iter1, _Iter2> operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const @@ -655,6 +655,7 @@ namespace ranges typename _Proj1 = identity, typename _Proj2 = identity> requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> + [[nodiscard]] constexpr mismatch_result<iterator_t<_Range1>, iterator_t<_Range2>> operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const @@ -675,7 +676,7 @@ namespace ranges typename _Pred = ranges::equal_to, typename _Proj1 = identity, typename _Proj2 = identity> requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - constexpr subrange<_Iter1> + [[nodiscard]] constexpr subrange<_Iter1> operator()(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const @@ -719,7 +720,7 @@ namespace ranges typename _Proj1 = identity, typename _Proj2 = identity> requires indirectly_comparable<iterator_t<_Range1>, iterator_t<_Range2>, _Pred, _Proj1, _Proj2> - constexpr borrowed_subrange_t<_Range1> + [[nodiscard]] constexpr borrowed_subrange_t<_Range1> operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const { @@ -737,7 +738,7 @@ namespace ranges template<typename _Tp, typename _Proj = identity, indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less> - constexpr const _Tp& + [[nodiscard]] constexpr const _Tp& operator()(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) const { @@ -754,13 +755,13 @@ namespace ranges _Comp = ranges::less> requires indirectly_copyable_storable<iterator_t<_Range>, range_value_t<_Range>*> - constexpr range_value_t<_Range> + [[nodiscard]] constexpr range_value_t<_Range> operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const { auto __first = ranges::begin(__r); auto __last = ranges::end(__r); __glibcxx_assert(__first != __last); - auto __result = *__first; + range_value_t<_Range> __result(*__first); while (++__first != __last) { auto&& __tmp = *__first; @@ -775,7 +776,7 @@ namespace ranges template<copyable _Tp, typename _Proj = identity, indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less> - constexpr _Tp + [[nodiscard]] constexpr _Tp operator()(initializer_list<_Tp> __r, _Comp __comp = {}, _Proj __proj = {}) const { @@ -793,7 +794,7 @@ namespace ranges indirect_binary_predicate<projected<_Iter, _Proj>, projected<_Iter, _Proj>> _Pred = ranges::equal_to> - constexpr _Iter + [[nodiscard]] constexpr _Iter operator()(_Iter __first, _Sent __last, _Pred __pred = {}, _Proj __proj = {}) const { @@ -814,7 +815,7 @@ namespace ranges indirect_binary_predicate< projected<iterator_t<_Range>, _Proj>, projected<iterator_t<_Range>, _Proj>> _Pred = ranges::equal_to> - constexpr borrowed_iterator_t<_Range> + [[nodiscard]] constexpr borrowed_iterator_t<_Range> operator()(_Range&& __r, _Pred __pred = {}, _Proj __proj = {}) const { return (*this)(ranges::begin(__r), ranges::end(__r), diff --git a/libstdc++-v3/include/bits/refwrap.h b/libstdc++-v3/include/bits/refwrap.h index 612715e..5d9f8c8 100644 --- a/libstdc++-v3/include/bits/refwrap.h +++ b/libstdc++-v3/include/bits/refwrap.h @@ -457,6 +457,40 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) /// @} +#if __glibcxx_common_reference_wrapper // C++ >= 20 + namespace __detail + { + template<typename _Tp> + constexpr bool __is_ref_wrapper = false; + + template<typename _Tp> + constexpr bool __is_ref_wrapper<reference_wrapper<_Tp>> = true; + + template<typename _Rp, typename _Tp, typename _RQual, typename _TQual> + concept __ref_wrap_common_reference_exists_with = __is_ref_wrapper<_Rp> + && requires { typename common_reference_t<typename _Rp::type&, _TQual>; } + && convertible_to<_RQual, common_reference_t<typename _Rp::type&, _TQual>>; + } // namespace __detail + + template<typename _Rp, typename _Tp, + template<typename> class _RQual, template<typename> class _TQual> + requires __detail::__ref_wrap_common_reference_exists_with<_Rp, _Tp, + _RQual<_Rp>, _TQual<_Tp>> + && (!__detail::__ref_wrap_common_reference_exists_with<_Tp, _Rp, + _TQual<_Tp>, _RQual<_Rp>>) + struct basic_common_reference<_Rp, _Tp, _RQual, _TQual> + { using type = common_reference_t<typename _Rp::type&, _TQual<_Tp>>; }; + + template<typename _Tp, typename _Rp, + template<typename> class _TQual, template<typename> class _RQual> + requires __detail::__ref_wrap_common_reference_exists_with<_Rp, _Tp, + _RQual<_Rp>, _TQual<_Tp>> + && (!__detail::__ref_wrap_common_reference_exists_with<_Tp, _Rp, + _TQual<_Tp>, _RQual<_Rp>>) + struct basic_common_reference<_Tp, _Rp, _TQual, _RQual> + { using type = common_reference_t<typename _Rp::type&, _TQual<_Tp>>; }; +#endif + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/regex.tcc b/libstdc++-v3/include/bits/regex.tcc index b94fe44..48917cd 100644 --- a/libstdc++-v3/include/bits/regex.tcc +++ b/libstdc++-v3/include/bits/regex.tcc @@ -331,20 +331,53 @@ namespace __detail && __c == __fctyp.widen('_')); } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr template<typename _Ch_type> int regex_traits<_Ch_type>:: value(_Ch_type __ch, int __radix) const { - std::basic_istringstream<char_type> __is(string_type(1, __ch)); - long __v; - if (__radix == 8) - __is >> std::oct; - else if (__radix == 16) - __is >> std::hex; - __is >> __v; - return __is.fail() ? -1 : __v; + if constexpr (sizeof(_Ch_type) > 1) + { + const auto& __ctyp = std::use_facet<ctype<_Ch_type>>(_M_locale); + const char __c = __ctyp.narrow(__ch, '\0'); + return regex_traits<char>{}.value(__c, __radix); + } + else + { + const char __c = static_cast<char>(__ch); + const char __max_digit = __radix == 8 ? '7' : '9'; + if ('0' <= __c && __c <= __max_digit) + return __c - '0'; + if (__radix < 16) + return -1; + switch (__c) + { + case 'a': + case 'A': + return 10; + case 'b': + case 'B': + return 11; + case 'c': + case 'C': + return 12; + case 'd': + case 'D': + return 13; + case 'e': + case 'E': + return 14; + case 'f': + case 'F': + return 15; + default: + return -1; + } + } } +#pragma GCC diagnostic pop template<typename _Bi_iter, typename _Alloc> template<typename _Out_iter> diff --git a/libstdc++-v3/include/bits/regex_automaton.tcc b/libstdc++-v3/include/bits/regex_automaton.tcc index 8a82646..4d566c6 100644 --- a/libstdc++-v3/include/bits/regex_automaton.tcc +++ b/libstdc++-v3/include/bits/regex_automaton.tcc @@ -28,6 +28,10 @@ * Do not attempt to use it directly. @headername{regex} */ +#ifdef _GLIBCXX_DEBUG +# include <ostream> +#endif + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/bits/sat_arith.h b/libstdc++-v3/include/bits/sat_arith.h index 97545d2..bce86d9 100644 --- a/libstdc++-v3/include/bits/sat_arith.h +++ b/libstdc++-v3/include/bits/sat_arith.h @@ -46,7 +46,7 @@ namespace std _GLIBCXX_VISIBILITY(default) _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Add two integers, with saturation in case of overflow. - template<typename _Tp> requires __is_standard_integer<_Tp>::value + template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value constexpr _Tp add_sat(_Tp __x, _Tp __y) noexcept { @@ -62,7 +62,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } /// Subtract one integer from another, with saturation in case of overflow. - template<typename _Tp> requires __is_standard_integer<_Tp>::value + template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value constexpr _Tp sub_sat(_Tp __x, _Tp __y) noexcept { @@ -78,7 +78,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } /// Multiply two integers, with saturation in case of overflow. - template<typename _Tp> requires __is_standard_integer<_Tp>::value + template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value constexpr _Tp mul_sat(_Tp __x, _Tp __y) noexcept { @@ -87,14 +87,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __z; if constexpr (is_unsigned_v<_Tp>) return __gnu_cxx::__int_traits<_Tp>::__max; - else if (__x < 0 != __y < 0) + else if ((__x < 0) != (__y < 0)) return __gnu_cxx::__int_traits<_Tp>::__min; else return __gnu_cxx::__int_traits<_Tp>::__max; } /// Divide one integer by another, with saturation in case of overflow. - template<typename _Tp> requires __is_standard_integer<_Tp>::value + template<typename _Tp> requires __is_signed_or_unsigned_integer<_Tp>::value constexpr _Tp div_sat(_Tp __x, _Tp __y) noexcept { @@ -107,8 +107,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Divide one integer by another, with saturation in case of overflow. template<typename _Res, typename _Tp> - requires __is_standard_integer<_Res>::value - && __is_standard_integer<_Tp>::value + requires __is_signed_or_unsigned_integer<_Res>::value + && __is_signed_or_unsigned_integer<_Tp>::value constexpr _Res saturate_cast(_Tp __x) noexcept { diff --git a/libstdc++-v3/include/bits/semaphore_base.h b/libstdc++-v3/include/bits/semaphore_base.h index d8f9bd8..cb815d3 100644 --- a/libstdc++-v3/include/bits/semaphore_base.h +++ b/libstdc++-v3/include/bits/semaphore_base.h @@ -34,231 +34,279 @@ #pragma GCC system_header #endif +#include <bits/version.h> + +#ifdef __glibcxx_semaphore // C++ >= 20 && hosted && atomic_wait #include <bits/atomic_base.h> #include <bits/chrono.h> -#if __glibcxx_atomic_wait #include <bits/atomic_timed_wait.h> #include <ext/numeric_traits.h> -#endif // __cpp_lib_atomic_wait - -#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE -# include <cerrno> // errno, EINTR, EAGAIN etc. -# include <limits.h> // SEM_VALUE_MAX -# include <semaphore.h> // sem_t, sem_init, sem_wait, sem_post etc. -#elif defined(_GLIBCXX_USE_POSIX_SEMAPHORE) -# warning "POSIX semaphore not available, ignoring _GLIBCXX_USE_POSIX_SEMAPHORE" -# undef _GLIBCXX_USE_POSIX_SEMAPHORE -#endif namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION -#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE - struct __platform_semaphore + struct __semaphore_impl { - using __clock_t = chrono::system_clock; -#ifdef SEM_VALUE_MAX - static constexpr ptrdiff_t _S_max = SEM_VALUE_MAX; -#else - static constexpr ptrdiff_t _S_max = _POSIX_SEM_VALUE_MAX; -#endif + using __count_type = ptrdiff_t; - explicit __platform_semaphore(ptrdiff_t __count) noexcept - { - sem_init(&_M_semaphore, 0, __count); - } + static constexpr ptrdiff_t _S_max + = __gnu_cxx::__int_traits<__count_type>::__max; - __platform_semaphore(const __platform_semaphore&) = delete; - __platform_semaphore& operator=(const __platform_semaphore&) = delete; + constexpr explicit + __semaphore_impl(__count_type __count) noexcept + : _M_counter(__count) + { } - ~__platform_semaphore() - { sem_destroy(&_M_semaphore); } + __semaphore_impl(const __semaphore_impl&) = delete; + __semaphore_impl& operator=(const __semaphore_impl&) = delete; - _GLIBCXX_ALWAYS_INLINE void - _M_acquire() noexcept - { - while (sem_wait(&_M_semaphore)) - if (errno != EINTR) - std::__terminate(); - } + // Load the current counter value. + _GLIBCXX_ALWAYS_INLINE __count_type + _M_get_current() const noexcept + { return __atomic_impl::load(&_M_counter, memory_order::acquire); } + // Try to acquire the semaphore (i.e. decrement the counter). + // Returns false if the current counter is zero, or if another thread + // changes the value first. In the latter case, __cur is set to the new + // value. _GLIBCXX_ALWAYS_INLINE bool - _M_try_acquire() noexcept + _M_do_try_acquire(__count_type& __cur) noexcept { - while (sem_trywait(&_M_semaphore)) - { - if (errno == EAGAIN) // already locked - return false; - else if (errno != EINTR) - std::__terminate(); - // else got EINTR so retry - } - return true; + if (__cur == 0) + return false; // Cannot decrement when it's already zero. + + return __atomic_impl::compare_exchange_strong(&_M_counter, + __cur, __cur - 1, + memory_order::acquire, + memory_order::relaxed); } - _GLIBCXX_ALWAYS_INLINE void - _M_release(ptrdiff_t __update) noexcept + // Keep trying to acquire the semaphore in a loop until it succeeds. + void + _M_acquire() noexcept { - for(; __update != 0; --__update) - if (sem_post(&_M_semaphore)) - std::__terminate(); + auto __vfn = [this]{ return _M_get_current(); }; + _Available __is_available{__vfn()}; + while (!_M_do_try_acquire(__is_available._M_val)) + if (!__is_available()) + std::__atomic_wait_address(&_M_counter, __is_available, __vfn, true); } + // Try to acquire the semaphore, retrying a small number of times + // in case of contention. bool - _M_try_acquire_until_impl(const chrono::time_point<__clock_t>& __atime) - noexcept + _M_try_acquire() noexcept { - auto __s = chrono::time_point_cast<chrono::seconds>(__atime); - auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s); - - struct timespec __ts = - { - static_cast<std::time_t>(__s.time_since_epoch().count()), - static_cast<long>(__ns.count()) - }; - - while (sem_timedwait(&_M_semaphore, &__ts)) - { - if (errno == ETIMEDOUT) - return false; - else if (errno != EINTR) - std::__terminate(); - } - return true; + // The fastest implementation of this function is just _M_do_try_acquire + // but that can fail under contention even when _M_count > 0. + // Using _M_try_acquire_for(0ns) will retry a few times in a loop. + return _M_try_acquire_for(__detail::__wait_clock_t::duration{}); } template<typename _Clock, typename _Duration> bool - _M_try_acquire_until(const chrono::time_point<_Clock, - _Duration>& __atime) noexcept + _M_try_acquire_until(const chrono::time_point<_Clock, _Duration>& __atime) noexcept { - if constexpr (std::is_same_v<__clock_t, _Clock>) - { - using _Dur = __clock_t::duration; - return _M_try_acquire_until_impl(chrono::ceil<_Dur>(__atime)); - } - else - { - // TODO: if _Clock is monotonic_clock we could use - // sem_clockwait with CLOCK_MONOTONIC. - - const typename _Clock::time_point __c_entry = _Clock::now(); - const auto __s_entry = __clock_t::now(); - const auto __delta = __atime - __c_entry; - const auto __s_atime = __s_entry + __delta; - if (_M_try_acquire_until_impl(__s_atime)) - return true; - - // We got a timeout when measured against __clock_t but - // we need to check against the caller-supplied clock - // to tell whether we should return a timeout. - return (_Clock::now() < __atime); - } + auto __vfn = [this]{ return _M_get_current(); }; + _Available __is_available{__vfn()}; + while (!_M_do_try_acquire(__is_available._M_val)) + if (!__is_available()) + if (!std::__atomic_wait_address_until(&_M_counter, __is_available, + __vfn, __atime, true)) + return false; // timed out + return true; } template<typename _Rep, typename _Period> - _GLIBCXX_ALWAYS_INLINE bool - _M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime) - noexcept - { return _M_try_acquire_until(__clock_t::now() + __rtime); } + bool + _M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime) noexcept + { + auto __vfn = [this]{ return _M_get_current(); }; + _Available __is_available{__vfn()}; + while (!_M_do_try_acquire(__is_available._M_val)) + if (!__is_available()) + if (!std::__atomic_wait_address_for(&_M_counter, __is_available, + __vfn, __rtime, true)) + return false; // timed out + return true; + } + + _GLIBCXX_ALWAYS_INLINE ptrdiff_t + _M_release(ptrdiff_t __update) noexcept + { + auto __old = __atomic_impl::fetch_add(&_M_counter, __update, + memory_order::release); + if (__old == 0 && __update > 0) + __atomic_notify_address(&_M_counter, true, true); + return __old; + } private: - sem_t _M_semaphore; + struct _Available + { + __count_type _M_val; // Cache of the last value loaded from _M_counter. + + // Returns true if the cached value is non-zero and so it should be + // possible to acquire the semaphore. + bool operator()() const noexcept { return _M_val > 0; } + + // Argument should be the latest value of the counter. + // Returns true (and caches the value) if it's non-zero, meaning it + // should be possible to acquire the semaphore. Returns false otherwise. + bool operator()(__count_type __cur) noexcept + { + if (__cur == 0) + return false; + _M_val = __cur; + return true; + } + }; + + alignas(__atomic_ref<__count_type>::required_alignment) + __count_type _M_counter; }; -#endif // _GLIBCXX_HAVE_POSIX_SEMAPHORE -#if __glibcxx_atomic_wait - struct __atomic_semaphore + // Optimized specialization using __platform_wait (if available) + template<bool _Binary> + struct __platform_semaphore_impl { - static constexpr ptrdiff_t _S_max = __gnu_cxx::__int_traits<int>::__max; - explicit __atomic_semaphore(__detail::__platform_wait_t __count) noexcept - : _M_counter(__count) + using __count_type = __detail::__platform_wait_t; + + static consteval ptrdiff_t + _S_calc_max() { - __glibcxx_assert(__count >= 0 && __count <= _S_max); + if (_Binary) + return 1; + else if ((ptrdiff_t)__gnu_cxx::__int_traits<__count_type>::__max < 0) + return __gnu_cxx::__int_traits<ptrdiff_t>::__max; + else + return __gnu_cxx::__int_traits<__count_type>::__max; } - __atomic_semaphore(const __atomic_semaphore&) = delete; - __atomic_semaphore& operator=(const __atomic_semaphore&) = delete; + static constexpr ptrdiff_t _S_max = _S_calc_max(); + + constexpr explicit + __platform_semaphore_impl(__count_type __count) noexcept + : _M_counter(__count) + { } + + __platform_semaphore_impl(__platform_semaphore_impl&) = delete; + __platform_semaphore_impl& operator=(const __platform_semaphore_impl&) = delete; + + // Load the current counter value. + _GLIBCXX_ALWAYS_INLINE __count_type + _M_get_current() const noexcept + { + if constexpr (_Binary) + return 1; // Not necessarily true, but optimistically assume it is. + else + return __atomic_impl::load(&_M_counter, memory_order::acquire); + } - static _GLIBCXX_ALWAYS_INLINE bool - _S_do_try_acquire(__detail::__platform_wait_t* __counter) noexcept + // Try to acquire the semaphore (i.e. decrement the counter). + // Returns false if the current counter is zero, or if another thread + // changes the value first. In the latter case, __cur is set to the new + // value. + _GLIBCXX_ALWAYS_INLINE bool + _M_do_try_acquire(__count_type& __cur) noexcept { - auto __old = __atomic_impl::load(__counter, memory_order::acquire); - if (__old == 0) - return false; + if (__cur == 0) + return false; // Cannot decrement when it's already zero. - return __atomic_impl::compare_exchange_strong(__counter, - __old, __old - 1, + return __atomic_impl::compare_exchange_strong(&_M_counter, + __cur, __cur - 1, memory_order::acquire, memory_order::relaxed); } - _GLIBCXX_ALWAYS_INLINE void + // Keep trying to acquire the semaphore in a loop until it succeeds. + void _M_acquire() noexcept { - auto const __pred = - [this] { return _S_do_try_acquire(&this->_M_counter); }; - std::__atomic_wait_address_bare(&_M_counter, __pred); + auto __val = _M_get_current(); + while (!_M_do_try_acquire(__val)) + if (__val == 0) + { + std::__atomic_wait_address_v(&_M_counter, __val, __ATOMIC_ACQUIRE, + true); + __val = _M_get_current(); + } } + // Try to acquire the semaphore. bool _M_try_acquire() noexcept { - auto const __pred = - [this] { return _S_do_try_acquire(&this->_M_counter); }; - return std::__detail::__atomic_spin(__pred); + if constexpr (_Binary) + { + __count_type __val = 1; + // Do not expect much contention on binary semaphore, only try once. + return _M_do_try_acquire(__val); + } + else + // Fastest implementation of this function is just _M_do_try_acquire + // but that can fail under contention even when _M_count > 0. + // Using _M_try_acquire_for(0ns) will retry a few times in a loop. + return _M_try_acquire_for(__detail::__wait_clock_t::duration{}); } template<typename _Clock, typename _Duration> - _GLIBCXX_ALWAYS_INLINE bool - _M_try_acquire_until(const chrono::time_point<_Clock, - _Duration>& __atime) noexcept + bool + _M_try_acquire_until(const chrono::time_point<_Clock, _Duration>& __atime) noexcept { - auto const __pred = - [this] { return _S_do_try_acquire(&this->_M_counter); }; - - return __atomic_wait_address_until_bare(&_M_counter, __pred, __atime); + auto __val = _M_get_current(); + while (!_M_do_try_acquire(__val)) + if (__val == 0) + { + if (!std::__atomic_wait_address_until_v(&_M_counter, 0, + __ATOMIC_ACQUIRE, + __atime, true)) + return false; // timed out + __val = _M_get_current(); + } + return true; } template<typename _Rep, typename _Period> - _GLIBCXX_ALWAYS_INLINE bool - _M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime) - noexcept + bool + _M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime) noexcept { - auto const __pred = - [this] { return _S_do_try_acquire(&this->_M_counter); }; - - return __atomic_wait_address_for_bare(&_M_counter, __pred, __rtime); + auto __val = _M_get_current(); + while (!_M_do_try_acquire(__val)) + if (__val == 0) + { + if (!std::__atomic_wait_address_for_v(&_M_counter, 0, + __ATOMIC_ACQUIRE, + __rtime, true)) + return false; // timed out + __val = _M_get_current(); + } + return true; } - _GLIBCXX_ALWAYS_INLINE void + _GLIBCXX_ALWAYS_INLINE ptrdiff_t _M_release(ptrdiff_t __update) noexcept { - if (0 < __atomic_impl::fetch_add(&_M_counter, __update, memory_order_release)) - return; - if (__update > 1) - __atomic_notify_address_bare(&_M_counter, true); - else - __atomic_notify_address_bare(&_M_counter, true); -// FIXME - Figure out why this does not wake a waiting thread -// __atomic_notify_address_bare(&_M_counter, false); + auto __old = __atomic_impl::fetch_add(&_M_counter, __update, + memory_order::release); + if (__old == 0 && __update > 0) + __atomic_notify_address(&_M_counter, true, true); + return __old; } - private: - alignas(__detail::__platform_wait_alignment) - __detail::__platform_wait_t _M_counter; + protected: + alignas(__detail::__platform_wait_alignment) __count_type _M_counter; }; -#endif // __cpp_lib_atomic_wait - -// Note: the _GLIBCXX_USE_POSIX_SEMAPHORE macro can be used to force the -// use of Posix semaphores (sem_t). Doing so however, alters the ABI. -#if defined __glibcxx_atomic_wait && !_GLIBCXX_USE_POSIX_SEMAPHORE - using __semaphore_impl = __atomic_semaphore; -#elif _GLIBCXX_HAVE_POSIX_SEMAPHORE - using __semaphore_impl = __platform_semaphore; -#endif + + template<ptrdiff_t _Max, typename _Tp = __detail::__platform_wait_t> + using _Semaphore_impl + = __conditional_t<__platform_wait_uses_type<_Tp> + && _Max <= __gnu_cxx::__int_traits<_Tp>::__max, + __platform_semaphore_impl<(_Max <= 1)>, + __semaphore_impl>; _GLIBCXX_END_NAMESPACE_VERSION } // namespace std +#endif // __glibcxx_semaphore #endif // _GLIBCXX_SEMAPHORE_BASE_H diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h index a196a0f..f2b4601 100644 --- a/libstdc++-v3/include/bits/shared_ptr.h +++ b/libstdc++-v3/include/bits/shared_ptr.h @@ -909,6 +909,64 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>> { }; +#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26 + + /** + * @brief Provides ownership-based hashing. + * @headerfile memory + * @since C++26 + */ + struct owner_hash + { + template<typename _Tp> + size_t + operator()(const shared_ptr<_Tp>& __s) const noexcept + { return __s.owner_hash(); } + + template<typename _Tp> + size_t + operator()(const weak_ptr<_Tp>& __s) const noexcept + { return __s.owner_hash(); } + + using is_transparent = void; + }; + + /** + * @brief Provides ownership-based mixed equality comparisons of + * shared and weak pointers. + * @headerfile memory + * @since C++26 + */ + struct owner_equal + { + template<typename _Tp1, typename _Tp2> + bool + operator()(const shared_ptr<_Tp1>& __lhs, + const shared_ptr<_Tp2>& __rhs) const noexcept + { return __lhs.owner_equal(__rhs); } + + template<typename _Tp1, typename _Tp2> + bool + operator()(const shared_ptr<_Tp1>& __lhs, + const weak_ptr<_Tp2>& __rhs) const noexcept + { return __lhs.owner_equal(__rhs); } + + template<typename _Tp1, typename _Tp2> + bool + operator()(const weak_ptr<_Tp1>& __lhs, + const shared_ptr<_Tp2>& __rhs) const noexcept + { return __lhs.owner_equal(__rhs); } + + template<typename _Tp1, typename _Tp2> + bool + operator()(const weak_ptr<_Tp1>& __lhs, + const weak_ptr<_Tp2>& __rhs) const noexcept + { return __lhs.owner_equal(__rhs); } + + using is_transparent = void; + }; +#endif + /** * @brief Base class allowing use of the member function `shared_from_this`. * @headerfile memory diff --git a/libstdc++-v3/include/bits/shared_ptr_atomic.h b/libstdc++-v3/include/bits/shared_ptr_atomic.h index cc7841a..cbc4bf6 100644 --- a/libstdc++-v3/include/bits/shared_ptr_atomic.h +++ b/libstdc++-v3/include/bits/shared_ptr_atomic.h @@ -392,6 +392,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class _Sp_atomic { using value_type = _Tp; + using element_type = typename _Tp::element_type; friend struct atomic<_Tp>; @@ -420,7 +421,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ~_Atomic_count() { - auto __val = _M_val.load(memory_order_relaxed); + auto __val = _AtomicRef(_M_val).load(memory_order_relaxed); _GLIBCXX_TSAN_MUTEX_DESTROY(&_M_val); __glibcxx_assert(!(__val & _S_lock_bit)); if (auto __pi = reinterpret_cast<pointer>(__val)) @@ -442,18 +443,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { // To acquire the lock we flip the LSB from 0 to 1. - auto __current = _M_val.load(memory_order_relaxed); + _AtomicRef __aref(_M_val); + auto __current = __aref.load(memory_order_relaxed); while (__current & _S_lock_bit) { #if __glibcxx_atomic_wait __detail::__thread_relax(); #endif - __current = _M_val.load(memory_order_relaxed); + __current = __aref.load(memory_order_relaxed); } _GLIBCXX_TSAN_MUTEX_TRY_LOCK(&_M_val); - while (!_M_val.compare_exchange_strong(__current, + while (!__aref.compare_exchange_strong(__current, __current | _S_lock_bit, __o, memory_order_relaxed)) @@ -474,7 +476,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION unlock(memory_order __o) const noexcept { _GLIBCXX_TSAN_MUTEX_PRE_UNLOCK(&_M_val); - _M_val.fetch_sub(1, __o); + _AtomicRef(_M_val).fetch_sub(1, __o); _GLIBCXX_TSAN_MUTEX_POST_UNLOCK(&_M_val); } @@ -487,7 +489,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __o = memory_order_release; auto __x = reinterpret_cast<uintptr_t>(__c._M_pi); _GLIBCXX_TSAN_MUTEX_PRE_UNLOCK(&_M_val); - __x = _M_val.exchange(__x, __o); + __x = _AtomicRef(_M_val).exchange(__x, __o); _GLIBCXX_TSAN_MUTEX_POST_UNLOCK(&_M_val); __c._M_pi = reinterpret_cast<pointer>(__x & ~_S_lock_bit); } @@ -495,19 +497,45 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __glibcxx_atomic_wait // Precondition: caller holds lock! void - _M_wait_unlock(memory_order __o) const noexcept + _M_wait_unlock(const element_type* const& __ptr, memory_order __o) const noexcept { + auto __old_ptr = __ptr; _GLIBCXX_TSAN_MUTEX_PRE_UNLOCK(&_M_val); - auto __v = _M_val.fetch_sub(1, memory_order_relaxed); + uintptr_t __old_pi + = _AtomicRef(_M_val).fetch_sub(1, memory_order_relaxed) - 1u; _GLIBCXX_TSAN_MUTEX_POST_UNLOCK(&_M_val); - _M_val.wait(__v & ~_S_lock_bit, __o); + + // Ensure that the correct value of _M_ptr is visible after locking, + // by upgrading relaxed or consume to acquire. + auto __lo = __o; + if (__o != memory_order_seq_cst) + __lo = memory_order_acquire; + + std::__atomic_wait_address( + &_M_val, + [=, &__ptr, this](uintptr_t __new_pi) + { + if (__old_pi != (__new_pi & ~_S_lock_bit)) + // control block changed, we can wake up + return true; + + // control block is same, we need to check if ptr changed, + // the lock needs to be taken first, the value of pi may have + // also been updated in meantime, so reload it + __new_pi = reinterpret_cast<uintptr_t>(this->lock(__lo)); + auto __new_ptr = __ptr; + this->unlock(memory_order_relaxed); + // wake up if either of the values changed + return __new_pi != __old_pi || __new_ptr != __old_ptr; + }, + [__o, this] { return _AtomicRef(_M_val).load(__o); }); } void notify_one() noexcept { _GLIBCXX_TSAN_MUTEX_PRE_SIGNAL(&_M_val); - _M_val.notify_one(); + _AtomicRef(_M_val).notify_one(); _GLIBCXX_TSAN_MUTEX_POST_SIGNAL(&_M_val); } @@ -515,17 +543,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION notify_all() noexcept { _GLIBCXX_TSAN_MUTEX_PRE_SIGNAL(&_M_val); - _M_val.notify_all(); + _AtomicRef(_M_val).notify_all(); _GLIBCXX_TSAN_MUTEX_POST_SIGNAL(&_M_val); } #endif private: - mutable __atomic_base<uintptr_t> _M_val{0}; + using _AtomicRef = __atomic_ref<uintptr_t>; + alignas(_AtomicRef::required_alignment) mutable uintptr_t _M_val{0}; static constexpr uintptr_t _S_lock_bit{1}; }; - typename _Tp::element_type* _M_ptr = nullptr; + element_type* _M_ptr = nullptr; _Atomic_count _M_refcount; static typename _Atomic_count::pointer @@ -608,7 +637,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { auto __pi = _M_refcount.lock(memory_order_acquire); if (_M_ptr == __old._M_ptr && __pi == __old._M_refcount._M_pi) - _M_refcount._M_wait_unlock(__o); + _M_refcount._M_wait_unlock(_M_ptr, __o); else _M_refcount.unlock(memory_order_relaxed); } diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h index b4be1b4..9af706a 100644 --- a/libstdc++-v3/include/bits/shared_ptr_base.h +++ b/libstdc++-v3/include/bits/shared_ptr_base.h @@ -148,7 +148,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Increment the use count (used when the count is greater than zero). void _M_add_ref_copy() - { __gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1); } + { _S_chk(__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1)); } // Increment the use count if it is non-zero, throw otherwise. void @@ -200,7 +200,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Increment the weak count. void _M_weak_add_ref() noexcept - { __gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1); } + { + // _M_weak_count can always use negative values because it cannot be + // observed by users (unlike _M_use_count). See _S_chk for details. + constexpr _Atomic_word __max = -1; + if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, 1) == __max) + [[__unlikely__]] __builtin_trap(); + } // Decrement the weak count. void @@ -224,19 +230,87 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION long _M_get_use_count() const noexcept { - // No memory barrier is used here so there is no synchronization - // with other threads. - return __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED); + // No memory barrier is used here so there is no synchronization + // with other threads. + auto __count = __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED); + + // If long is wider than _Atomic_word then we can treat _Atomic_word + // as unsigned, and so double its usable range. If the widths are the + // same then casting to unsigned and then to long is a no-op. + return static_cast<_Unsigned_count_type>(__count); } private: _Sp_counted_base(_Sp_counted_base const&) = delete; _Sp_counted_base& operator=(_Sp_counted_base const&) = delete; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wignored-attributes" + // This is only to be used for arithmetic, not for atomic ops. + using _Unsigned_count_type = make_unsigned<_Atomic_word>::type; +#pragma GCC diagnostic pop + + // Called when incrementing _M_use_count to cause a trap on overflow. + // This should be passed the value of the counter before the increment. + static void + _S_chk(_Atomic_word __count) + { + constexpr _Atomic_word __max_atomic_word = _Unsigned_count_type(-1)/2; + + // __max is the maximum allowed value for the shared reference count. + // All valid reference count values need to fit into [0,LONG_MAX) + // because users can observe the count via shared_ptr::use_count(). + // + // When long is wider than _Atomic_word, _M_use_count can go negative + // and the cast in _Sp_counted_base::use_count() will turn it into a + // positive value suitable for returning to users. The implementation + // only cares whether _M_use_count reaches zero after a decrement, + // so negative values are not a problem internally. + // So when possible, use -1 for __max (incrementing past that would + // overflow _M_use_count to 0, which means an empty shared_ptr). + // + // When long is not wider than _Atomic_word, __max is just the type's + // maximum positive value. We cannot use negative counts because they + // would not fit in [0,LONG_MAX) after casting to an unsigned type, + // which would cause use_count() to return bogus values. + constexpr _Atomic_word __max + = sizeof(long) > sizeof(_Atomic_word) ? -1 : __max_atomic_word; + + if (__count == __max) [[__unlikely__]] + __builtin_trap(); + } + _Atomic_word _M_use_count; // #shared _Atomic_word _M_weak_count; // #weak + (#shared != 0) }; + // We use __atomic_add_single and __exchange_and_add_single in the _S_single + // member specializations because they use unsigned arithmetic and so avoid + // undefined overflow. + template<> + inline void + _Sp_counted_base<_S_single>::_M_add_ref_copy() + { + _S_chk(_M_use_count); + __gnu_cxx::__atomic_add_single(&_M_use_count, 1); + } + + template<> + inline void + _Sp_counted_base<_S_single>::_M_weak_release() noexcept + { + if (__gnu_cxx::__exchange_and_add_single(&_M_weak_count, -1) == 1) + _M_destroy(); + } + + template<> + inline long + _Sp_counted_base<_S_single>::_M_get_use_count() const noexcept + { + return static_cast<_Unsigned_count_type>(_M_use_count); + } + + template<> inline bool _Sp_counted_base<_S_single>:: @@ -244,7 +318,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (_M_use_count == 0) return false; - ++_M_use_count; + _M_add_ref_copy(); return true; } @@ -254,8 +328,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_add_ref_lock_nothrow() noexcept { __gnu_cxx::__scoped_lock sentry(*this); - if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0) + if (auto __c = __gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1)) + _S_chk(__c); + else { + // Count was zero, so we cannot lock it to get a shared_ptr. + // Reset to zero. This isn't racy, because there are no shared_ptr + // objects using this count and any other weak_ptr objects using it + // must call this function to modify _M_use_count, so would be + // synchronized by the mutex. _M_use_count = 0; return false; } @@ -279,23 +360,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1, true, __ATOMIC_ACQ_REL, __ATOMIC_RELAXED)); + _S_chk(__count); return true; } template<> inline void - _Sp_counted_base<_S_single>::_M_add_ref_copy() - { ++_M_use_count; } - - template<> - inline void _Sp_counted_base<_S_single>::_M_release() noexcept { - if (--_M_use_count == 0) + if (__gnu_cxx::__exchange_and_add_single(&_M_use_count, -1) == 1) { - _M_dispose(); - if (--_M_weak_count == 0) - _M_destroy(); + _M_dispose(); + _M_weak_release(); } } @@ -364,25 +440,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #pragma GCC diagnostic pop } - template<> - inline void - _Sp_counted_base<_S_single>::_M_weak_add_ref() noexcept - { ++_M_weak_count; } - - template<> - inline void - _Sp_counted_base<_S_single>::_M_weak_release() noexcept - { - if (--_M_weak_count == 0) - _M_destroy(); - } - - template<> - inline long - _Sp_counted_base<_S_single>::_M_get_use_count() const noexcept - { return _M_use_count; } - - // Forward declarations. template<typename _Tp, _Lock_policy _Lp = __default_lock_policy> class __shared_ptr; @@ -1122,6 +1179,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_less(const __weak_count<_Lp>& __rhs) const noexcept { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } +#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26 + size_t + _M_owner_hash() const noexcept + { return std::hash<_Sp_counted_base<_Lp>*>()(this->_M_pi); } +#endif + // Friend function injected into enclosing namespace and found by ADL friend inline bool operator==(const __shared_count& __a, const __shared_count& __b) noexcept @@ -1225,6 +1288,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_less(const __shared_count<_Lp>& __rhs) const noexcept { return std::less<_Sp_counted_base<_Lp>*>()(this->_M_pi, __rhs._M_pi); } +#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26 + size_t + _M_owner_hash() const noexcept + { return std::hash<_Sp_counted_base<_Lp>*>()(this->_M_pi); } +#endif + // Friend function injected into enclosing namespace and found by ADL friend inline bool operator==(const __weak_count& __a, const __weak_count& __b) noexcept @@ -1715,6 +1784,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return _M_refcount._M_less(__rhs._M_refcount); } /// @} +#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26 + size_t owner_hash() const noexcept { return _M_refcount._M_owner_hash(); } + + template<typename _Tp1> + bool + owner_equal(__shared_ptr<_Tp1, _Lp> const& __rhs) const noexcept + { return _M_refcount == __rhs._M_refcount; } + + template<typename _Tp1> + bool + owner_equal(__weak_ptr<_Tp1, _Lp> const& __rhs) const noexcept + { return _M_refcount == __rhs._M_refcount; } +#endif + protected: // This constructor is non-standard, it is used by allocate_shared. template<typename _Alloc, typename... _Args> @@ -1986,6 +2069,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp, _Lock_policy _Lp> class __weak_ptr { + public: + using element_type = typename remove_extent<_Tp>::type; + + private: template<typename _Yp, typename _Res = void> using _Compatible = typename enable_if<__sp_compatible_with<_Yp*, _Tp*>::value, _Res>::type; @@ -1994,9 +2081,44 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Yp> using _Assignable = _Compatible<_Yp, __weak_ptr&>; - public: - using element_type = typename remove_extent<_Tp>::type; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr + // Helper for construction/assignment: + template<typename _Yp> + static element_type* + _S_safe_upcast(const __weak_ptr<_Yp, _Lp>& __r) + { + // We know that _Yp and _Tp are compatible, that is, either + // _Yp* is convertible to _Tp* or _Yp is U[N] and _Tp is U cv []. + + // If _Yp is the same as _Tp after removing extents and cv + // qualifications, there's no pointer adjustments to do. This + // also allows us to support incomplete types. + using _At = typename remove_cv<typename remove_extent<_Tp>::type>::type; + using _Bt = typename remove_cv<typename remove_extent<_Yp>::type>::type; + if constexpr (is_same<_At, _Bt>::value) + return __r._M_ptr; + // If they're not the same type, but they're both scalars, + // we again don't need any adjustment. This allows us to support e.g. + // pointers to a differently cv qualified type X. + else if constexpr (__and_<is_scalar<_At>, is_scalar<_Bt>>::value) + return __r._M_ptr; +#if _GLIBCXX_USE_BUILTIN_TRAIT(__builtin_is_virtual_base_of) + // If _Tp is not a virtual base class of _Yp, the pointer + // conversion does not require dereferencing __r._M_ptr; just + // rely on the implicit conversion. + else if constexpr (!__builtin_is_virtual_base_of(_Tp, _Yp)) + return __r._M_ptr; +#endif + // Expensive path; must lock() and do the pointer conversion while + // a shared_ptr keeps the pointee alive (because we may need + // to dereference). + else + return __r.lock().get(); + } +#pragma GCC diagnostic pop + public: constexpr __weak_ptr() noexcept : _M_ptr(nullptr), _M_refcount() { } @@ -2021,8 +2143,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // in multithreaded programs __r._M_ptr may be invalidated at any point. template<typename _Yp, typename = _Compatible<_Yp>> __weak_ptr(const __weak_ptr<_Yp, _Lp>& __r) noexcept - : _M_refcount(__r._M_refcount) - { _M_ptr = __r.lock().get(); } + : _M_ptr(_S_safe_upcast(__r)), _M_refcount(__r._M_refcount) + { } template<typename _Yp, typename = _Compatible<_Yp>> __weak_ptr(const __shared_ptr<_Yp, _Lp>& __r) noexcept @@ -2035,7 +2157,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Yp, typename = _Compatible<_Yp>> __weak_ptr(__weak_ptr<_Yp, _Lp>&& __r) noexcept - : _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount)) + : _M_ptr(_S_safe_upcast(__r)), _M_refcount(std::move(__r._M_refcount)) { __r._M_ptr = nullptr; } __weak_ptr& @@ -2045,7 +2167,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Assignable<_Yp> operator=(const __weak_ptr<_Yp, _Lp>& __r) noexcept { - _M_ptr = __r.lock().get(); + _M_ptr = _S_safe_upcast(__r); _M_refcount = __r._M_refcount; return *this; } @@ -2070,7 +2192,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Assignable<_Yp> operator=(__weak_ptr<_Yp, _Lp>&& __r) noexcept { - _M_ptr = __r.lock().get(); + _M_ptr = _S_safe_upcast(__r); _M_refcount = std::move(__r._M_refcount); __r._M_ptr = nullptr; return *this; @@ -2098,6 +2220,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION owner_before(const __weak_ptr<_Tp1, _Lp>& __rhs) const noexcept { return _M_refcount._M_less(__rhs._M_refcount); } +#ifdef __glibcxx_smart_ptr_owner_equality // >= C++26 + size_t owner_hash() const noexcept { return _M_refcount._M_owner_hash(); } + + template<typename _Tp1> + bool + owner_equal(const __shared_ptr<_Tp1, _Lp> & __rhs) const noexcept + { return _M_refcount == __rhs._M_refcount; } + + template<typename _Tp1> + bool + owner_equal(const __weak_ptr<_Tp1, _Lp> & __rhs) const noexcept + { return _M_refcount == __rhs._M_refcount; } +#endif + void reset() noexcept { __weak_ptr().swap(*this); } diff --git a/libstdc++-v3/include/bits/std_abs.h b/libstdc++-v3/include/bits/std_abs.h index 35ec4d3..3d805e6 100644 --- a/libstdc++-v3/include/bits/std_abs.h +++ b/libstdc++-v3/include/bits/std_abs.h @@ -103,6 +103,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; } #endif +#if defined __STRICT_ANSI__ && defined __SIZEOF_INT128__ + // In strict modes __GLIBCXX_TYPE_INT_N_0 is not defined for __int128, + // but we want to always define std::abs(__int128). + __extension__ inline _GLIBCXX_CONSTEXPR __int128 + abs(__int128 __x) { return __x >= 0 ? __x : -__x; } +#endif + #if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) constexpr _Float16 abs(_Float16 __x) @@ -137,7 +144,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __gnu_cxx::__bfloat16_t(__builtin_fabsf(__x)); } #endif -#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) +#if defined(_GLIBCXX_USE_FLOAT128) __extension__ inline _GLIBCXX_CONSTEXPR __float128 abs(__float128 __x) diff --git a/libstdc++-v3/include/bits/std_mutex.h b/libstdc++-v3/include/bits/std_mutex.h index 777097b..5f9f154 100644 --- a/libstdc++-v3/include/bits/std_mutex.h +++ b/libstdc++-v3/include/bits/std_mutex.h @@ -39,6 +39,7 @@ #else #include <errno.h> // EBUSY +#include <bits/chrono.h> #include <bits/functexcept.h> #include <bits/gthr.h> @@ -210,8 +211,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __gthread_cond_t _M_cond; #endif }; - /// @endcond +namespace chrono +{ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++17-extensions" + // Convert a time_point to an absolute time represented as __gthread_time_t + // (which is typically just a typedef for struct timespec). + template<typename _Clock, typename _Dur> + [[__nodiscard__]] _GLIBCXX14_CONSTEXPR inline + __gthread_time_t + __to_timeout_gthread_time_t(const time_point<_Clock, _Dur>& __t) + { + auto __ts = chrono::__to_timeout_timespec(__t.time_since_epoch()); + if constexpr (is_same<::timespec, __gthread_time_t>::value) + return __ts; + else if constexpr (is_convertible<::timespec, __gthread_time_t>::value) + return __ts; + else if constexpr (is_scalar<__gthread_time_t>::value) // Assume seconds: + return static_cast<__gthread_time_t>(__ts.tv_sec); + else // Assume this works and the members are in the correct order: + return __gthread_time_t{ __ts.tv_sec, __ts.tv_nsec }; + } +#pragma GCC diagnostic pop +} + /// @endcond #endif // _GLIBCXX_HAS_GTHREADS /// Do not acquire ownership of the mutex. diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h index 71ead10..bbd1800 100644 --- a/libstdc++-v3/include/bits/stl_algo.h +++ b/libstdc++-v3/include/bits/stl_algo.h @@ -85,21 +85,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Iterator, typename _Compare> _GLIBCXX20_CONSTEXPR void - __move_median_to_first(_Iterator __result,_Iterator __a, _Iterator __b, + __move_median_to_first(_Iterator __result, _Iterator __a, _Iterator __b, _Iterator __c, _Compare __comp) { - if (__comp(__a, __b)) + if (__comp(*__a, *__b)) { - if (__comp(__b, __c)) + if (__comp(*__b, *__c)) std::iter_swap(__result, __b); - else if (__comp(__a, __c)) + else if (__comp(*__a, *__c)) std::iter_swap(__result, __c); else std::iter_swap(__result, __a); } - else if (__comp(__a, __c)) + else if (__comp(*__a, *__c)) std::iter_swap(__result, __a); - else if (__comp(__b, __c)) + else if (__comp(*__b, *__c)) std::iter_swap(__result, __c); else std::iter_swap(__result, __b); @@ -113,7 +113,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Predicate __pred) { return std::__find_if(__first, __last, - __gnu_cxx::__ops::__negate(__pred)); + __gnu_cxx::__ops::not1(__pred)); } /// Like find_if_not(), but uses and updates a count of the @@ -125,7 +125,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __find_if_not_n(_InputIterator __first, _Distance& __len, _Predicate __pred) { for (; __len; --__len, (void) ++__first) - if (!__pred(__first)) + if (!__pred(*__first)) break; return __first; } @@ -162,7 +162,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __n = __count; _ForwardIterator __i = __first; ++__i; - while (__i != __last && __n != 1 && __unary_pred(__i)) + while (__i != __last && __n != 1 && __unary_pred(*__i)) { ++__i; --__n; @@ -201,10 +201,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // __first here is always pointing to one past the last element of // next possible match. _RandomAccessIter __backTrack = __first; - while (__unary_pred(--__backTrack)) + while (__unary_pred(*--__backTrack)) { if (--__remainder == 0) - return (__first - __count); // Success + return __first - _DistanceType(__count); // Success } __remainder = __count + 1 - (__first - __backTrack); } @@ -339,7 +339,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return std::__find_end(__first1, __last1, __first2, __last2, std::__iterator_category(__first1), std::__iterator_category(__first2), - __gnu_cxx::__ops::__iter_equal_to_iter()); + __gnu_cxx::__ops::equal_to()); } /** @@ -390,7 +390,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return std::__find_end(__first1, __last1, __first2, __last2, std::__iterator_category(__first1), std::__iterator_category(__first2), - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __comp); } #if __cplusplus >= 201103L @@ -470,8 +470,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, typename iterator_traits<_InputIterator>::value_type>) __glibcxx_requires_valid_range(__first, __last); - return std::__find_if_not(__first, __last, - __gnu_cxx::__ops::__pred_iter(__pred)); + return std::__find_if_not(__first, __last, __pred); } /** @@ -551,7 +550,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _OutputIterator __result, _Predicate __pred) { for (; __first != __last; ++__first) - if (!__pred(__first)) + if (!__pred(*__first)) { *__result = *__first; ++__result; @@ -588,7 +587,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); return std::__remove_copy_if(__first, __last, __result, - __gnu_cxx::__ops::__iter_equals_val(__value)); + __gnu_cxx::__ops::__equal_to(__value)); } /** @@ -621,8 +620,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename iterator_traits<_InputIterator>::value_type>) __glibcxx_requires_valid_range(__first, __last); - return std::__remove_copy_if(__first, __last, __result, - __gnu_cxx::__ops::__pred_iter(__pred)); + return std::__remove_copy_if(__first, __last, __result, __pred); } #if __cplusplus >= 201103L @@ -780,7 +778,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); return std::__remove_if(__first, __last, - __gnu_cxx::__ops::__iter_equals_val(__value)); + __gnu_cxx::__ops::__equal_to(__value)); } /** @@ -813,8 +811,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename iterator_traits<_ForwardIterator>::value_type>) __glibcxx_requires_valid_range(__first, __last); - return std::__remove_if(__first, __last, - __gnu_cxx::__ops::__pred_iter(__pred)); + return std::__remove_if(__first, __last, __pred); } template<typename _ForwardIterator, typename _BinaryPredicate> @@ -828,7 +825,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _ForwardIterator __next = __first; while (++__next != __last) { - if (__binary_pred(__first, __next)) + if (__binary_pred(*__first, *__next)) return __first; __first = __next; } @@ -850,7 +847,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _ForwardIterator __dest = __first; ++__first; while (++__first != __last) - if (!__binary_pred(__dest, __first)) + if (!__binary_pred(*__dest, *__first)) *++__dest = _GLIBCXX_MOVE(*__first); return ++__dest; } @@ -881,8 +878,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename iterator_traits<_ForwardIterator>::value_type>) __glibcxx_requires_valid_range(__first, __last); - return std::__unique(__first, __last, - __gnu_cxx::__ops::__iter_equal_to_iter()); + return std::__unique(__first, __last, __gnu_cxx::__ops::equal_to()); } /** @@ -914,66 +910,48 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typename iterator_traits<_ForwardIterator>::value_type>) __glibcxx_requires_valid_range(__first, __last); - return std::__unique(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); + return std::__unique(__first, __last, __binary_pred); } - /** - * This is an uglified - * unique_copy(_InputIterator, _InputIterator, _OutputIterator, - * _BinaryPredicate) - * overloaded for forward iterators and output iterator as result. - */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4269. unique_copy passes arguments to its predicate backwards + + // Implementation of std::unique_copy for forward iterators. + // This case is easy, just compare *i with *(i-1). template<typename _ForwardIterator, typename _OutputIterator, typename _BinaryPredicate> _GLIBCXX20_CONSTEXPR _OutputIterator __unique_copy(_ForwardIterator __first, _ForwardIterator __last, _OutputIterator __result, _BinaryPredicate __binary_pred, - forward_iterator_tag, output_iterator_tag) + forward_iterator_tag) { - // concept requirements -- iterators already checked - __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, - typename iterator_traits<_ForwardIterator>::value_type, - typename iterator_traits<_ForwardIterator>::value_type>) - - _ForwardIterator __next = __first; + _ForwardIterator __prev = __first; *__result = *__first; - while (++__next != __last) - if (!__binary_pred(__first, __next)) + while (++__first != __last) + if (!__binary_pred(*__prev, *__first)) { - __first = __next; *++__result = *__first; + __prev = __first; } return ++__result; } - /** - * This is an uglified - * unique_copy(_InputIterator, _InputIterator, _OutputIterator, - * _BinaryPredicate) - * overloaded for input iterators and output iterator as result. - */ + // Implementation of std::unique_copy for non-forward iterators, + // where we cannot compare with elements written to the output. template<typename _InputIterator, typename _OutputIterator, typename _BinaryPredicate> _GLIBCXX20_CONSTEXPR _OutputIterator - __unique_copy(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, _BinaryPredicate __binary_pred, - input_iterator_tag, output_iterator_tag) + __unique_copy_1(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryPredicate __binary_pred, + __false_type) { - // concept requirements -- iterators already checked - __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, - typename iterator_traits<_InputIterator>::value_type, - typename iterator_traits<_InputIterator>::value_type>) - - typename iterator_traits<_InputIterator>::value_type __value = *__first; - __decltype(__gnu_cxx::__ops::__iter_comp_val(__binary_pred)) - __rebound_pred - = __gnu_cxx::__ops::__iter_comp_val(__binary_pred); + typedef typename iterator_traits<_InputIterator>::value_type _Val; + _Val __value = *__first; *__result = __value; while (++__first != __last) - if (!__rebound_pred(__first, __value)) + if (!__binary_pred(__value, *__first)) { __value = *__first; *++__result = __value; @@ -981,31 +959,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return ++__result; } - /** - * This is an uglified - * unique_copy(_InputIterator, _InputIterator, _OutputIterator, - * _BinaryPredicate) - * overloaded for input iterators and forward iterator as result. - */ + // Implementation of std::unique_copy for non-forward iterators, + // where we can compare with the last element written to the output. template<typename _InputIterator, typename _ForwardIterator, typename _BinaryPredicate> - _GLIBCXX20_CONSTEXPR _ForwardIterator - __unique_copy(_InputIterator __first, _InputIterator __last, - _ForwardIterator __result, _BinaryPredicate __binary_pred, - input_iterator_tag, forward_iterator_tag) + __unique_copy_1(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _BinaryPredicate __binary_pred, + __true_type) { - // concept requirements -- iterators already checked - __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, - typename iterator_traits<_ForwardIterator>::value_type, - typename iterator_traits<_InputIterator>::value_type>) *__result = *__first; while (++__first != __last) - if (!__binary_pred(__result, __first)) + if (!__binary_pred(*__result, *__first)) *++__result = *__first; return ++__result; } + // Implementation of std::unique_copy for non-forward iterators. + // We cannot compare *i to *(i-1) so we need to either make a copy + // or compare with the last element written to the output range. + template<typename _InputIterator, typename _OutputIterator, + typename _BinaryPredicate> + _GLIBCXX20_CONSTEXPR + _OutputIterator + __unique_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryPredicate __binary_pred, + input_iterator_tag) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2439. unique_copy() sometimes can't fall back to reading its output + typedef iterator_traits<_InputIterator> _InItTraits; + typedef iterator_traits<_OutputIterator> _OutItTraits; + typedef typename _OutItTraits::iterator_category _Cat; + const bool __output_is_fwd = __is_base_of(forward_iterator_tag, _Cat); + const bool __same_type = __is_same(typename _OutItTraits::value_type, + typename _InItTraits::value_type); + typedef __truth_type<__output_is_fwd && __same_type> __cmp_with_output; + return std::__unique_copy_1(__first, __last, __result, __binary_pred, + typename __cmp_with_output::__type()); + } + + /** * This is an uglified reverse(_BidirectionalIterator, * _BidirectionalIterator) @@ -1259,9 +1253,12 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2) { if (__is_pod(_ValueType) && __k == 1) { + _RandomAccessIterator __mid = __p + _Distance(__n - 1); + _RandomAccessIterator __end = __mid; + ++__end; _ValueType __t = _GLIBCXX_MOVE(*__p); - _GLIBCXX_MOVE3(__p + 1, __p + __n, __p); - *(__p + __n - 1) = _GLIBCXX_MOVE(__t); + _GLIBCXX_MOVE3(__p + _Distance(1), __end, __p); + *__mid = _GLIBCXX_MOVE(__t); return __ret; } _RandomAccessIterator __q = __p + __k; @@ -1282,8 +1279,11 @@ _GLIBCXX_BEGIN_INLINE_ABI_NAMESPACE(_V2) __k = __n - __k; if (__is_pod(_ValueType) && __k == 1) { - _ValueType __t = _GLIBCXX_MOVE(*(__p + __n - 1)); - _GLIBCXX_MOVE_BACKWARD3(__p, __p + __n - 1, __p + __n); + _RandomAccessIterator __mid = __p + _Distance(__n - 1); + _RandomAccessIterator __end = __mid; + ++__end; + _ValueType __t = _GLIBCXX_MOVE(*__mid); + _GLIBCXX_MOVE_BACKWARD3(__p, __mid, __end); *__p = _GLIBCXX_MOVE(__t); return __ret; } @@ -1440,10 +1440,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) // partition /// This is a helper function... - /// Requires __first != __last and !__pred(__first) + /// Requires __first != __last and !__pred(*__first) /// and __len == distance(__first, __last). /// - /// !__pred(__first) allows us to guarantee that we don't + /// !__pred(*__first) allows us to guarantee that we don't /// move-assign an element onto itself. template<typename _ForwardIterator, typename _Pointer, typename _Predicate, typename _Distance> @@ -1463,14 +1463,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) _ForwardIterator __result1 = __first; _Pointer __result2 = __buffer; - // The precondition guarantees that !__pred(__first), so + // The precondition guarantees that !__pred(*__first), so // move that element to the buffer before starting the loop. // This ensures that we only call __pred once per element. *__result2 = _GLIBCXX_MOVE(*__first); ++__result2; ++__first; for (; __first != __last; ++__first) - if (__pred(__first)) + if (__pred(*__first)) { *__result1 = _GLIBCXX_MOVE(*__first); ++__result1; @@ -1576,8 +1576,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) typename iterator_traits<_ForwardIterator>::value_type>) __glibcxx_requires_valid_range(__first, __last); - return std::__stable_partition(__first, __last, - __gnu_cxx::__ops::__pred_iter(__pred)); + return std::__stable_partition(__first, __last, __pred); } #endif // HOSTED @@ -1593,7 +1592,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) { std::__make_heap(__first, __middle, __comp); for (_RandomAccessIterator __i = __middle; __i < __last; ++__i) - if (__comp(__i, __first)) + if (__comp(*__i, *__first)) std::__pop_heap(__first, __middle, __i, __comp); } @@ -1626,7 +1625,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) std::__make_heap(__result_first, __result_real_last, __comp); while (__first != __last) { - if (__comp(__first, __result_first)) + if (__comp(*__first, *__result_first)) std::__adjust_heap(__result_first, _DistanceType(0), _DistanceType(__result_real_last - __result_first), @@ -1684,7 +1683,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) return std::__partial_sort_copy(__first, __last, __result_first, __result_last, - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::less()); } /** @@ -1739,7 +1738,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) return std::__partial_sort_copy(__first, __last, __result_first, __result_last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __comp); } /// @cond undocumented @@ -1755,7 +1754,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __val = _GLIBCXX_MOVE(*__last); _RandomAccessIterator __next = __last; --__next; - while (__comp(__val, __next)) + while (__comp(__val, *__next)) { *__last = _GLIBCXX_MOVE(*__next); __last = __next; @@ -1771,20 +1770,22 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __insertion_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { - if (__first == __last) return; + if (__first == __last) + return; - for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) + typedef iterator_traits<_RandomAccessIterator> _IterTraits; + typedef typename _IterTraits::difference_type _Dist; + + for (_RandomAccessIterator __i = __first + _Dist(1); __i != __last; ++__i) { - if (__comp(__i, __first)) + if (__comp(*__i, *__first)) { - typename iterator_traits<_RandomAccessIterator>::value_type - __val = _GLIBCXX_MOVE(*__i); - _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + 1); + typename _IterTraits::value_type __val = _GLIBCXX_MOVE(*__i); + _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + _Dist(1)); *__first = _GLIBCXX_MOVE(__val); } else - std::__unguarded_linear_insert(__i, - __gnu_cxx::__ops::__val_comp_iter(__comp)); + std::__unguarded_linear_insert(__i, __comp); } } @@ -1796,8 +1797,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) _RandomAccessIterator __last, _Compare __comp) { for (_RandomAccessIterator __i = __first; __i != __last; ++__i) - std::__unguarded_linear_insert(__i, - __gnu_cxx::__ops::__val_comp_iter(__comp)); + std::__unguarded_linear_insert(__i, __comp); } /** @@ -1813,10 +1813,13 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __final_insertion_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { - if (__last - __first > int(_S_threshold)) + typename iterator_traits<_RandomAccessIterator>::difference_type + __threshold = _S_threshold; + + if (__last - __first > __threshold) { - std::__insertion_sort(__first, __first + int(_S_threshold), __comp); - std::__unguarded_insertion_sort(__first + int(_S_threshold), __last, + std::__insertion_sort(__first, __first + __threshold, __comp); + std::__unguarded_insertion_sort(__first + __threshold, __last, __comp); } else @@ -1833,10 +1836,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) { while (true) { - while (__comp(__first, __pivot)) + while (__comp(*__first, *__pivot)) ++__first; --__last; - while (__comp(__pivot, __last)) + while (__comp(*__pivot, *__last)) --__last; if (!(__first < __last)) return __first; @@ -1852,10 +1855,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __unguarded_partition_pivot(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) { - _RandomAccessIterator __mid = __first + (__last - __first) / 2; - std::__move_median_to_first(__first, __first + 1, __mid, __last - 1, + typedef iterator_traits<_RandomAccessIterator> _IterTraits; + typedef typename _IterTraits::difference_type _Dist; + + _RandomAccessIterator __mid = __first + _Dist((__last - __first) / 2); + _RandomAccessIterator __second = __first + _Dist(1); + std::__move_median_to_first(__first, __second, __mid, __last - _Dist(1), __comp); - return std::__unguarded_partition(__first + 1, __last, __first, __comp); + return std::__unguarded_partition(__second, __last, __first, __comp); } template<typename _RandomAccessIterator, typename _Compare> @@ -1917,11 +1924,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) _RandomAccessIterator __last, _Size __depth_limit, _Compare __comp) { + _RandomAccessIterator __after_nth = __nth; + ++__after_nth; + while (__last - __first > 3) { if (__depth_limit == 0) { - std::__heap_select(__first, __nth + 1, __last, __comp); + std::__heap_select(__first, __after_nth, __last, __comp); // Place the nth largest element in its final position. std::iter_swap(__first, __nth); return; @@ -1971,8 +1981,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_partitioned_lower_pred(__first, __last, __val, __comp); - return std::__lower_bound(__first, __last, __val, - __gnu_cxx::__ops::__iter_comp_val(__comp)); + return std::__lower_bound(__first, __last, __val, __comp); } template<typename _ForwardIterator, typename _Tp, typename _Compare> @@ -1991,7 +2000,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) _DistanceType __half = __len >> 1; _ForwardIterator __middle = __first; std::advance(__middle, __half); - if (__comp(__val, __middle)) + if (__comp(__val, *__middle)) __len = __half; else { @@ -2027,7 +2036,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_partitioned_upper(__first, __last, __val); return std::__upper_bound(__first, __last, __val, - __gnu_cxx::__ops::__val_less_iter()); + __gnu_cxx::__ops::less()); } /** @@ -2058,17 +2067,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_partitioned_upper_pred(__first, __last, __val, __comp); - return std::__upper_bound(__first, __last, __val, - __gnu_cxx::__ops::__val_comp_iter(__comp)); + return std::__upper_bound(__first, __last, __val, __comp); } - template<typename _ForwardIterator, typename _Tp, - typename _CompareItTp, typename _CompareTpIt> + template<typename _ForwardIterator, typename _Tp, typename _Compare> _GLIBCXX20_CONSTEXPR pair<_ForwardIterator, _ForwardIterator> __equal_range(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __val, - _CompareItTp __comp_it_val, _CompareTpIt __comp_val_it) + const _Tp& __val, _Compare __comp) { typedef typename iterator_traits<_ForwardIterator>::difference_type _DistanceType; @@ -2080,21 +2086,21 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) _DistanceType __half = __len >> 1; _ForwardIterator __middle = __first; std::advance(__middle, __half); - if (__comp_it_val(__middle, __val)) + if (__comp(*__middle, __val)) { __first = __middle; ++__first; __len = __len - __half - 1; } - else if (__comp_val_it(__val, __middle)) + else if (__comp(__val, *__middle)) __len = __half; else { _ForwardIterator __left - = std::__lower_bound(__first, __middle, __val, __comp_it_val); + = std::__lower_bound(__first, __middle, __val, __comp); std::advance(__first, __len); _ForwardIterator __right - = std::__upper_bound(++__middle, __first, __val, __comp_val_it); + = std::__upper_bound(++__middle, __first, __val, __comp); return pair<_ForwardIterator, _ForwardIterator>(__left, __right); } } @@ -2134,8 +2140,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_partitioned_upper(__first, __last, __val); return std::__equal_range(__first, __last, __val, - __gnu_cxx::__ops::__iter_less_val(), - __gnu_cxx::__ops::__val_less_iter()); + __gnu_cxx::__ops::less()); } /** @@ -2172,9 +2177,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_partitioned_upper_pred(__first, __last, __val, __comp); - return std::__equal_range(__first, __last, __val, - __gnu_cxx::__ops::__iter_comp_val(__comp), - __gnu_cxx::__ops::__val_comp_iter(__comp)); + return std::__equal_range(__first, __last, __val, __comp); } /** @@ -2203,8 +2206,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_partitioned_upper(__first, __last, __val); _ForwardIterator __i - = std::__lower_bound(__first, __last, __val, - __gnu_cxx::__ops::__iter_less_val()); + = std::__lower_bound(__first, __last, __val, __gnu_cxx::__ops::less()); return __i != __last && !(__val < *__i); } @@ -2239,8 +2241,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __val, __comp); _ForwardIterator __i - = std::__lower_bound(__first, __last, __val, - __gnu_cxx::__ops::__iter_comp_val(__comp)); + = std::__lower_bound(__first, __last, __val, __comp); return __i != __last && !bool(__comp(__val, *__i)); } @@ -2256,7 +2257,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) { while (__first1 != __last1 && __first2 != __last2) { - if (__comp(__first2, __first1)) + if (__comp(*__first2, *__first1)) { *__result = _GLIBCXX_MOVE(*__first2); ++__first2; @@ -2295,7 +2296,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) --__last2; while (true) { - if (__comp(__last2, __last1)) + if (__comp(*__last2, *__last1)) { *--__result = _GLIBCXX_MOVE(*__last1); if (__first1 == __last1) @@ -2401,8 +2402,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __len11 = __len1 / 2; std::advance(__first_cut, __len11); __second_cut - = std::__lower_bound(__middle, __last, *__first_cut, - __gnu_cxx::__ops::__iter_comp_val(__comp)); + = std::__lower_bound(__middle, __last, *__first_cut, __comp); __len22 = std::distance(__middle, __second_cut); } else @@ -2410,8 +2410,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __len22 = __len2 / 2; std::advance(__second_cut, __len22); __first_cut - = std::__upper_bound(__first, __middle, *__second_cut, - __gnu_cxx::__ops::__val_comp_iter(__comp)); + = std::__upper_bound(__first, __middle, *__second_cut, __comp); __len11 = std::distance(__first, __first_cut); } @@ -2445,7 +2444,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) if (__len1 + __len2 == 2) { - if (__comp(__middle, __first)) + if (__comp(*__middle, *__first)) std::iter_swap(__first, __middle); return; } @@ -2459,8 +2458,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __len11 = __len1 / 2; std::advance(__first_cut, __len11); __second_cut - = std::__lower_bound(__middle, __last, *__first_cut, - __gnu_cxx::__ops::__iter_comp_val(__comp)); + = std::__lower_bound(__middle, __last, *__first_cut, __comp); __len22 = std::distance(__middle, __second_cut); } else @@ -2468,8 +2466,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __len22 = __len2 / 2; std::advance(__second_cut, __len22); __first_cut - = std::__upper_bound(__first, __middle, *__second_cut, - __gnu_cxx::__ops::__val_comp_iter(__comp)); + = std::__upper_bound(__first, __middle, *__second_cut, __comp); __len11 = std::distance(__first, __first_cut); } @@ -2512,7 +2509,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) // [first,middle) and [middle,last). _TmpBuf __buf(__first, std::min(__len1, __len2)); - if (__builtin_expect(__buf.size() == __buf.requested_size(), true)) + if (__builtin_expect(__buf.size() == __buf._M_requested_size(), true)) std::__merge_adaptive (__first, __middle, __last, __len1, __len2, __buf.begin(), __comp); else if (__builtin_expect(__buf.begin() == 0, false)) @@ -2563,7 +2560,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_irreflexive(__first, __last); std::__inplace_merge(__first, __middle, __last, - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::less()); } /** @@ -2606,8 +2603,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_sorted_pred(__middle, __last, __comp); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - std::__inplace_merge(__first, __middle, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + std::__inplace_merge(__first, __middle, __last, __comp); } @@ -2621,7 +2617,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) { while (__first1 != __last1 && __first2 != __last2) { - if (__comp(__first2, __first1)) + if (__comp(*__first2, *__first1)) { *__result = _GLIBCXX_MOVE(*__first2); ++__first2; @@ -2786,9 +2782,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) { while (__first1 != __last1 && __first2 != __last2) { - if (__comp(__first2, __first1)) + if (__comp(*__first2, *__first1)) return false; - if (!__comp(__first1, __first2)) + if (!__comp(*__first1, *__first2)) ++__first2; ++__first1; } @@ -2835,7 +2831,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_irreflexive2(__first2, __last2); return std::__includes(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::less()); } /** @@ -2881,8 +2877,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); - return std::__includes(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + return std::__includes(__first1, __last1, __first2, __last2, __comp); } // nth_element @@ -2914,10 +2909,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) { _BidirectionalIterator __ii = __i; --__i; - if (__comp(__i, __ii)) + if (__comp(*__i, *__ii)) { _BidirectionalIterator __j = __last; - while (!__comp(__i, --__j)) + while (!__comp(*__i, *--__j)) {} std::iter_swap(__i, __j); std::__reverse(__ii, __last, @@ -2959,8 +2954,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive(__first, __last); - return std::__next_permutation - (__first, __last, __gnu_cxx::__ops::__iter_less_iter()); + return std::__next_permutation(__first, __last, __gnu_cxx::__ops::less()); } /** @@ -2993,8 +2987,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - return std::__next_permutation - (__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp)); + return std::__next_permutation(__first, __last, __comp); } template<typename _BidirectionalIterator, typename _Compare> @@ -3016,10 +3009,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) { _BidirectionalIterator __ii = __i; --__i; - if (__comp(__ii, __i)) + if (__comp(*__ii, *__i)) { _BidirectionalIterator __j = __last; - while (!__comp(--__j, __i)) + while (!__comp(*--__j, *__i)) {} std::iter_swap(__i, __j); std::__reverse(__ii, __last, @@ -3062,8 +3055,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive(__first, __last); - return std::__prev_permutation(__first, __last, - __gnu_cxx::__ops::__iter_less_iter()); + return std::__prev_permutation(__first, __last, __gnu_cxx::__ops::less()); } /** @@ -3096,8 +3088,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - return std::__prev_permutation(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + return std::__prev_permutation(__first, __last, __comp); } // replace @@ -3112,7 +3103,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) _Predicate __pred, const _Tp& __new_value) { for (; __first != __last; ++__first, (void)++__result) - if (__pred(__first)) + if (__pred(*__first)) *__result = __new_value; else *__result = *__first; @@ -3149,8 +3140,8 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_valid_range(__first, __last); return std::__replace_copy_if(__first, __last, __result, - __gnu_cxx::__ops::__iter_equals_val(__old_value), - __new_value); + __gnu_cxx::__ops::__equal_to(__old_value), + __new_value); } /** @@ -3184,9 +3175,8 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) typename iterator_traits<_InputIterator>::value_type>) __glibcxx_requires_valid_range(__first, __last); - return std::__replace_copy_if(__first, __last, __result, - __gnu_cxx::__ops::__pred_iter(__pred), - __new_value); + return std::__replace_copy_if(__first, __last, __result, __pred, + __new_value); } #if __cplusplus >= 201103L @@ -3230,7 +3220,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) _ForwardIterator __next = __first; for (++__next; __next != __last; __first = __next, (void)++__next) - if (__comp(__next, __first)) + if (__comp(*__next, *__first)) return __next; return __next; } @@ -3256,7 +3246,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_irreflexive(__first, __last); return std::__is_sorted_until(__first, __last, - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::less()); } /** @@ -3282,8 +3272,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - return std::__is_sorted_until(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + return std::__is_sorted_until(__first, __last, __comp); } /** @@ -3336,7 +3325,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) return std::make_pair(__first, __first); _ForwardIterator __min{}, __max{}; - if (__comp(__next, __first)) + if (__comp(*__next, *__first)) { __min = __next; __max = __first; @@ -3355,25 +3344,25 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __next = __first; if (++__next == __last) { - if (__comp(__first, __min)) + if (__comp(*__first, *__min)) __min = __first; - else if (!__comp(__first, __max)) + else if (!__comp(*__first, *__max)) __max = __first; break; } - if (__comp(__next, __first)) + if (__comp(*__next, *__first)) { - if (__comp(__next, __min)) + if (__comp(*__next, *__min)) __min = __next; - if (!__comp(__first, __max)) + if (!__comp(*__first, *__max)) __max = __first; } else { - if (__comp(__first, __min)) + if (__comp(*__first, *__min)) __min = __first; - if (!__comp(__next, __max)) + if (!__comp(*__next, *__max)) __max = __next; } @@ -3407,8 +3396,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive(__first, __last); - return std::__minmax_element(__first, __last, - __gnu_cxx::__ops::__iter_less_iter()); + return std::__minmax_element(__first, __last, __gnu_cxx::__ops::less()); } /** @@ -3437,8 +3425,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - return std::__minmax_element(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + return std::__minmax_element(__first, __last, __comp); } template<typename _Tp> @@ -3449,7 +3436,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_irreflexive(__l.begin(), __l.end()); pair<const _Tp*, const _Tp*> __p = std::__minmax_element(__l.begin(), __l.end(), - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::less()); return std::make_pair(*__p.first, *__p.second); } @@ -3460,8 +3447,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) { __glibcxx_requires_irreflexive_pred(__l.begin(), __l.end(), __comp); pair<const _Tp*, const _Tp*> __p = - std::__minmax_element(__l.begin(), __l.end(), - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + std::__minmax_element(__l.begin(), __l.end(), __comp); return std::make_pair(*__p.first, *__p.second); } @@ -3494,11 +3480,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) typename iterator_traits<_ForwardIterator2>::value_type>) __glibcxx_requires_valid_range(__first1, __last1); - return std::__is_permutation(__first1, __last1, __first2, - __gnu_cxx::__ops::__iter_comp_iter(__pred)); + return std::__is_permutation(__first1, __last1, __first2, __pred); } -#if __cplusplus > 201103L +#if __glibcxx_robust_nonmodifying_seq_ops // C++ >= 14 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr template<typename _ForwardIterator1, typename _ForwardIterator2, @@ -3526,7 +3511,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) // have the same elements in the same order. for (; __first1 != __last1 && __first2 != __last2; ++__first1, (void)++__first2) - if (!__pred(__first1, __first2)) + if (!__pred(*__first1, *__first2)) break; if constexpr (__ra_iters) @@ -3546,16 +3531,14 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan) { - if (__scan != std::__find_if(__first1, __scan, - __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))) + auto&& __scan_val = *__scan; + auto __scaneq = __gnu_cxx::__ops::bind1st(__pred, __scan_val); + if (__scan != std::__find_if(__first1, __scan, __scaneq)) continue; // We've seen this one before. - auto __matches = std::__count_if(__first2, __last2, - __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)); + auto __matches = std::__count_if(__first2, __last2, __scaneq); if (0 == __matches - || std::__count_if(__scan, __last1, - __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)) - != __matches) + || std::__count_if(__scan, __last1, __scaneq) != __matches) return false; } return true; @@ -3584,9 +3567,8 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_valid_range(__first1, __last1); __glibcxx_requires_valid_range(__first2, __last2); - return - std::__is_permutation(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_equal_to_iter()); + return std::__is_permutation(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::equal_to()); } /** @@ -3615,9 +3597,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __glibcxx_requires_valid_range(__first2, __last2); return std::__is_permutation(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_comp_iter(__pred)); + __pred); } -#endif // C++14 +#endif // __glibcxx_robust_nonmodifying_seq_ops #ifdef __glibcxx_clamp // C++ >= 17 /** @@ -3823,7 +3805,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO { if (__n2 <= 0) return __first; - auto __last = __first + __n2; + typename iterator_traits<_InputIterator>::difference_type __d = __n2; + auto __last = __first + __d; std::for_each(__first, __last, std::move(__f)); return __last; } @@ -3893,7 +3876,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO #endif return std::__find_if(__first, __last, - __gnu_cxx::__ops::__iter_equals_val(__val)); + __gnu_cxx::__ops::__equal_to(__val)); } /** @@ -3918,8 +3901,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO typename iterator_traits<_InputIterator>::value_type>) __glibcxx_requires_valid_range(__first, __last); - return std::__find_if(__first, __last, - __gnu_cxx::__ops::__pred_iter(__pred)); + return std::__find_if(__first, __last, __pred); } /** @@ -4024,7 +4006,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first, __last); return std::__adjacent_find(__first, __last, - __gnu_cxx::__ops::__iter_equal_to_iter()); + __gnu_cxx::__ops::equal_to()); } /** @@ -4051,8 +4033,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO typename iterator_traits<_ForwardIterator>::value_type>) __glibcxx_requires_valid_range(__first, __last); - return std::__adjacent_find(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); + return std::__adjacent_find(__first, __last, __binary_pred); } /** @@ -4076,7 +4057,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first, __last); return std::__count_if(__first, __last, - __gnu_cxx::__ops::__iter_equals_val(__value)); + __gnu_cxx::__ops::__equal_to(__value)); } /** @@ -4099,8 +4080,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO typename iterator_traits<_InputIterator>::value_type>) __glibcxx_requires_valid_range(__first, __last); - return std::__count_if(__first, __last, - __gnu_cxx::__ops::__pred_iter(__pred)); + return std::__count_if(__first, __last, __pred); } /** @@ -4145,7 +4125,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first2, __last2); return std::__search(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_equal_to_iter()); + __gnu_cxx::__ops::equal_to()); } /** @@ -4176,7 +4156,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first, __last); return std::__search_n(__first, __last, __count, - __gnu_cxx::__ops::__iter_equals_val(__val)); + __gnu_cxx::__ops::__equal_to(__val)); } @@ -4212,7 +4192,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first, __last); return std::__search_n(__first, __last, __count, - __gnu_cxx::__ops::__iter_comp_val(__binary_pred, __val)); + __gnu_cxx::__ops::bind2nd(__binary_pred, __val)); } #if __cplusplus >= 201703L @@ -4469,9 +4449,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO if (__first == __last) return __result; return std::__unique_copy(__first, __last, __result, - __gnu_cxx::__ops::__iter_equal_to_iter(), - std::__iterator_category(__first), - std::__iterator_category(__result)); + __gnu_cxx::__ops::equal_to(), + std::__iterator_category(__first)); } /** @@ -4505,13 +4484,14 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, typename iterator_traits<_InputIterator>::value_type>) __glibcxx_requires_valid_range(__first, __last); + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_InputIterator>::value_type, + typename iterator_traits<_InputIterator>::value_type>) if (__first == __last) return __result; - return std::__unique_copy(__first, __last, __result, - __gnu_cxx::__ops::__iter_comp_iter(__binary_pred), - std::__iterator_category(__first), - std::__iterator_category(__result)); + return std::__unique_copy(__first, __last, __result, __binary_pred, + std::__iterator_category(__first)); } #if __cplusplus <= 201103L || _GLIBCXX_USE_DEPRECATED @@ -4544,6 +4524,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO if (__first == __last) return; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _Dist; + #if RAND_MAX < __INT_MAX__ if (__builtin_expect((__last - __first) >= RAND_MAX / 4, 0)) { @@ -4551,14 +4534,15 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO // instead of using rand() for all the random numbers needed. unsigned __xss = (unsigned)std::rand() ^ ((unsigned)std::rand() << 15); - for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) + for (_RandomAccessIterator __i = __first + _Dist(1); __i != __last; + ++__i) { __xss += !__xss; __xss ^= __xss << 13; __xss ^= __xss >> 17; __xss ^= __xss << 5; - _RandomAccessIterator __j = __first - + (__xss % ((__i - __first) + 1)); + _RandomAccessIterator __j + = __first + _Dist(__xss % ((__i - __first) + 1)); if (__i != __j) std::iter_swap(__i, __j); } @@ -4566,11 +4550,11 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO } #endif - for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) + for (_RandomAccessIterator __i = __first + _Dist(1); __i != __last; ++__i) { // XXX rand() % N is not uniformly distributed - _RandomAccessIterator __j = __first - + (std::rand() % ((__i - __first) + 1)); + _RandomAccessIterator __j + = __first + _Dist(std::rand() % ((__i - __first) + 1)); if (__i != __j) std::iter_swap(__i, __j); } @@ -4611,9 +4595,14 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO if (__first == __last) return; - for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) + + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _Dist; + + for (_RandomAccessIterator __i = __first + _Dist(1); __i != __last; ++__i) { - _RandomAccessIterator __j = __first + __rand((__i - __first) + 1); + _RandomAccessIterator __j + = __first + _Dist(__rand((__i - __first) + 1)); if (__i != __j) std::iter_swap(__i, __j); } @@ -4688,7 +4677,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_irreflexive(__first, __last); std::__partial_sort(__first, __middle, __last, - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::less()); } /** @@ -4728,8 +4717,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__middle, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - std::__partial_sort(__first, __middle, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + std::__partial_sort(__first, __middle, __last, __comp); } /** @@ -4767,7 +4755,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO std::__introselect(__first, __nth, __last, std::__lg(__last - __first) * 2, - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::less()); } /** @@ -4808,7 +4796,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO std::__introselect(__first, __nth, __last, std::__lg(__last - __first) * 2, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + __comp); } /** @@ -4838,7 +4826,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive(__first, __last); - std::__sort(__first, __last, __gnu_cxx::__ops::__iter_less_iter()); + std::__sort(__first, __last, __gnu_cxx::__ops::less()); } /** @@ -4871,7 +4859,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp)); + std::__sort(__first, __last, __comp); } template<typename _InputIterator1, typename _InputIterator2, @@ -4884,7 +4872,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO { while (__first1 != __last1 && __first2 != __last2) { - if (__comp(__first2, __first1)) + if (__comp(*__first2, *__first1)) { *__result = *__first2; ++__first2; @@ -4942,9 +4930,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_irreflexive2(__first1, __last1); __glibcxx_requires_irreflexive2(__first2, __last2); - return _GLIBCXX_STD_A::__merge(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_less_iter()); + return _GLIBCXX_STD_A::__merge(__first1, __last1, __first2, __last2, + __result, __gnu_cxx::__ops::less()); } /** @@ -4993,9 +4980,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); - return _GLIBCXX_STD_A::__merge(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + return _GLIBCXX_STD_A::__merge(__first1, __last1, __first2, __last2, + __result, __comp); } template<typename _RandomAccessIterator, typename _Compare> @@ -5024,7 +5010,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO // so the buffer only needs to fit half the range at once. _TmpBuf __buf(__first, (__last - __first + 1) / 2); - if (__builtin_expect(__buf.requested_size() == __buf.size(), true)) + if (__builtin_expect(__buf._M_requested_size() == __buf.size(), true)) std::__stable_sort_adaptive(__first, __first + _DistanceType(__buf.size()), __last, __buf.begin(), __comp); @@ -5069,7 +5055,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_irreflexive(__first, __last); _GLIBCXX_STD_A::__stable_sort(__first, __last, - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::less()); } /** @@ -5105,13 +5091,11 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - _GLIBCXX_STD_A::__stable_sort(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + _GLIBCXX_STD_A::__stable_sort(__first, __last, __comp); } template<typename _InputIterator1, typename _InputIterator2, - typename _OutputIterator, - typename _Compare> + typename _OutputIterator, typename _Compare> _GLIBCXX20_CONSTEXPR _OutputIterator __set_union(_InputIterator1 __first1, _InputIterator1 __last1, @@ -5120,12 +5104,12 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO { while (__first1 != __last1 && __first2 != __last2) { - if (__comp(__first1, __first2)) + if (__comp(*__first1, *__first2)) { *__result = *__first1; ++__first1; } - else if (__comp(__first2, __first1)) + else if (__comp(*__first2, *__first1)) { *__result = *__first2; ++__first2; @@ -5187,9 +5171,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_irreflexive2(__first1, __last1); __glibcxx_requires_irreflexive2(__first2, __last2); - return _GLIBCXX_STD_A::__set_union(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_less_iter()); + return _GLIBCXX_STD_A::__set_union(__first1, __last1, __first2, __last2, + __result, __gnu_cxx::__ops::less()); } /** @@ -5238,14 +5221,12 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); - return _GLIBCXX_STD_A::__set_union(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + return _GLIBCXX_STD_A::__set_union(__first1, __last1, __first2, __last2, + __result, __comp); } template<typename _InputIterator1, typename _InputIterator2, - typename _OutputIterator, - typename _Compare> + typename _OutputIterator, typename _Compare> _GLIBCXX20_CONSTEXPR _OutputIterator __set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, @@ -5253,9 +5234,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO _OutputIterator __result, _Compare __comp) { while (__first1 != __last1 && __first2 != __last2) - if (__comp(__first1, __first2)) + if (__comp(*__first1, *__first2)) ++__first1; - else if (__comp(__first2, __first1)) + else if (__comp(*__first2, *__first1)) ++__first2; else { @@ -5309,9 +5290,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_irreflexive2(__first1, __last1); __glibcxx_requires_irreflexive2(__first2, __last2); - return _GLIBCXX_STD_A::__set_intersection(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_less_iter()); + return _GLIBCXX_STD_A:: + __set_intersection(__first1, __last1, __first2, __last2, + __result, __gnu_cxx::__ops::less()); } /** @@ -5359,14 +5340,13 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); - return _GLIBCXX_STD_A::__set_intersection(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + return _GLIBCXX_STD_A:: + __set_intersection(__first1, __last1, __first2, __last2, + __result, __comp); } template<typename _InputIterator1, typename _InputIterator2, - typename _OutputIterator, - typename _Compare> + typename _OutputIterator, typename _Compare> _GLIBCXX20_CONSTEXPR _OutputIterator __set_difference(_InputIterator1 __first1, _InputIterator1 __last1, @@ -5374,13 +5354,13 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO _OutputIterator __result, _Compare __comp) { while (__first1 != __last1 && __first2 != __last2) - if (__comp(__first1, __first2)) + if (__comp(*__first1, *__first2)) { *__result = *__first1; ++__first1; ++__result; } - else if (__comp(__first2, __first1)) + else if (__comp(*__first2, *__first1)) ++__first2; else { @@ -5434,9 +5414,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_irreflexive2(__first1, __last1); __glibcxx_requires_irreflexive2(__first2, __last2); - return _GLIBCXX_STD_A::__set_difference(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_less_iter()); + return _GLIBCXX_STD_A:: + __set_difference(__first1, __last1, __first2, __last2, __result, + __gnu_cxx::__ops::less()); } /** @@ -5486,9 +5466,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); - return _GLIBCXX_STD_A::__set_difference(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + return _GLIBCXX_STD_A:: + __set_difference(__first1, __last1, __first2, __last2, __result, + __comp); } template<typename _InputIterator1, typename _InputIterator2, @@ -5504,13 +5484,13 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO _Compare __comp) { while (__first1 != __last1 && __first2 != __last2) - if (__comp(__first1, __first2)) + if (__comp(*__first1, *__first2)) { *__result = *__first1; ++__first1; ++__result; } - else if (__comp(__first2, __first1)) + else if (__comp(*__first2, *__first1)) { *__result = *__first2; ++__first2; @@ -5569,9 +5549,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_irreflexive2(__first1, __last1); __glibcxx_requires_irreflexive2(__first2, __last2); - return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_less_iter()); + return _GLIBCXX_STD_A:: + __set_symmetric_difference(__first1, __last1, __first2, __last2, + __result, __gnu_cxx::__ops::less()); } /** @@ -5622,9 +5602,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); - return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + return _GLIBCXX_STD_A:: + __set_symmetric_difference(__first1, __last1, __first2, __last2, + __result, __comp); } template<typename _ForwardIterator, typename _Compare> @@ -5637,7 +5617,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO return __first; _ForwardIterator __result = __first; while (++__first != __last) - if (__comp(__first, __result)) + if (__comp(*__first, *__result)) __result = __first; return __result; } @@ -5651,8 +5631,8 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO */ template<typename _ForwardIterator> _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR - _ForwardIterator - inline min_element(_ForwardIterator __first, _ForwardIterator __last) + inline _ForwardIterator + min_element(_ForwardIterator __first, _ForwardIterator __last) { // concept requirements __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) @@ -5662,7 +5642,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_irreflexive(__first, __last); return _GLIBCXX_STD_A::__min_element(__first, __last, - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::less()); } /** @@ -5688,8 +5668,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - return _GLIBCXX_STD_A::__min_element(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + return _GLIBCXX_STD_A::__min_element(__first, __last, __comp); } template<typename _ForwardIterator, typename _Compare> @@ -5701,7 +5680,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO if (__first == __last) return __first; _ForwardIterator __result = __first; while (++__first != __last) - if (__comp(__result, __first)) + if (__comp(*__result, *__first)) __result = __first; return __result; } @@ -5726,7 +5705,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_irreflexive(__first, __last); return _GLIBCXX_STD_A::__max_element(__first, __last, - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::less()); } /** @@ -5752,54 +5731,51 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - return _GLIBCXX_STD_A::__max_element(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + return _GLIBCXX_STD_A::__max_element(__first, __last, __comp); } #if __cplusplus >= 201103L // N2722 + DR 915. template<typename _Tp> - _GLIBCXX14_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR inline _Tp min(initializer_list<_Tp> __l) { __glibcxx_requires_irreflexive(__l.begin(), __l.end()); return *_GLIBCXX_STD_A::__min_element(__l.begin(), __l.end(), - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::less()); } template<typename _Tp, typename _Compare> - _GLIBCXX14_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR inline _Tp min(initializer_list<_Tp> __l, _Compare __comp) { __glibcxx_requires_irreflexive_pred(__l.begin(), __l.end(), __comp); - return *_GLIBCXX_STD_A::__min_element(__l.begin(), __l.end(), - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + return *_GLIBCXX_STD_A::__min_element(__l.begin(), __l.end(), __comp); } template<typename _Tp> - _GLIBCXX14_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR inline _Tp max(initializer_list<_Tp> __l) { __glibcxx_requires_irreflexive(__l.begin(), __l.end()); return *_GLIBCXX_STD_A::__max_element(__l.begin(), __l.end(), - __gnu_cxx::__ops::__iter_less_iter()); + __gnu_cxx::__ops::less()); } template<typename _Tp, typename _Compare> - _GLIBCXX14_CONSTEXPR + _GLIBCXX_NODISCARD _GLIBCXX14_CONSTEXPR inline _Tp max(initializer_list<_Tp> __l, _Compare __comp) { __glibcxx_requires_irreflexive_pred(__l.begin(), __l.end(), __comp); - return *_GLIBCXX_STD_A::__max_element(__l.begin(), __l.end(), - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + return *_GLIBCXX_STD_A::__max_element(__l.begin(), __l.end(), __comp); } #endif // C++11 -#if __cplusplus >= 201402L +#if __cplusplus >= 201402L // C++17 std::sample and C++14 experimental::sample /// Reservoir sampling algorithm. template<typename _InputIterator, typename _RandomAccessIterator, typename _Size, typename _UniformRandomBitGenerator> diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h index 119dbe9..443cbef 100644 --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase.h @@ -1046,19 +1046,26 @@ _GLIBCXX_END_NAMESPACE_CONTAINER __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_2 __n) { return __n; } #endif #if defined(__GLIBCXX_TYPE_INT_N_3) - __extension__ inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_3 - __size_to_integer(__GLIBCXX_TYPE_INT_N_3 __n) { return __n; } __extension__ inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_3 + __size_to_integer(__GLIBCXX_TYPE_INT_N_3 __n) { return __n; } + __extension__ inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_3 __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_3 __n) { return __n; } #endif +#if defined(__STRICT_ANSI__) && defined(__SIZEOF_INT128__) + __extension__ inline _GLIBCXX_CONSTEXPR __int128 + __size_to_integer(__int128 __n) { return __n; } + __extension__ inline _GLIBCXX_CONSTEXPR unsigned __int128 + __size_to_integer(unsigned __int128 __n) { return __n; } +#endif + inline _GLIBCXX_CONSTEXPR long long __size_to_integer(float __n) { return (long long)__n; } inline _GLIBCXX_CONSTEXPR long long __size_to_integer(double __n) { return (long long)__n; } inline _GLIBCXX_CONSTEXPR long long __size_to_integer(long double __n) { return (long long)__n; } -#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) +#ifdef _GLIBCXX_USE_FLOAT128 __extension__ inline _GLIBCXX_CONSTEXPR long long __size_to_integer(__float128 __n) { return (long long)__n; } #endif @@ -1143,10 +1150,12 @@ _GLIBCXX_END_NAMESPACE_CONTAINER if (__n <= 0) return __first; - __glibcxx_requires_can_increment(__first, __n); + typename iterator_traits<_OutputIterator>::difference_type __d = __n; + __glibcxx_requires_can_increment(__first, __d); - std::__fill_a(__first, __first + __n, __value); - return __first + __n; + _OutputIterator __last = __first + __d; + std::__fill_a(__first, __last, __value); + return __last; } /** @@ -1303,11 +1312,11 @@ _GLIBCXX_END_NAMESPACE_CONTAINER __newlast1(_RAI1 __first1, _RAI1 __last1, _RAI2 __first2, _RAI2 __last2) { - const typename iterator_traits<_RAI1>::difference_type - __diff1 = __last1 - __first1; - const typename iterator_traits<_RAI2>::difference_type - __diff2 = __last2 - __first2; - return __diff2 < __diff1 ? __first1 + __diff2 : __last1; + typedef typename iterator_traits<_RAI1>::difference_type _Diff1; + typedef typename iterator_traits<_RAI2>::difference_type _Diff2; + const _Diff1 __diff1 = __last1 - __first1; + const _Diff2 __diff2 = __last2 - __first2; + return __diff2 < __diff1 ? __first1 + _Diff1(__diff2) : __last1; } template<typename _RAI> @@ -1331,9 +1340,9 @@ _GLIBCXX_END_NAMESPACE_CONTAINER for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2); ++__first1, (void)++__first2) { - if (__comp(__first1, __first2)) + if (__comp(*__first1, *__first2)) return true; - if (__comp(__first2, __first1)) + if (__comp(*__first2, *__first1)) return false; } return __first1 == __last1 && __first2 != __last2; @@ -1347,10 +1356,10 @@ _GLIBCXX_END_NAMESPACE_CONTAINER static bool __lc(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) { - using __gnu_cxx::__ops::__iter_less_iter; + using __gnu_cxx::__ops::less; return std::__lexicographical_compare_impl(__first1, __last1, __first2, __last2, - __iter_less_iter()); + less()); } template<typename _II1, typename _II2> @@ -1506,7 +1515,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER _DistanceType __half = __len >> 1; _ForwardIterator __middle = __first; std::advance(__middle, __half); - if (__comp(__middle, __val)) + if (__comp(*__middle, __val)) { __first = __middle; ++__first; @@ -1542,7 +1551,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER __glibcxx_requires_partitioned_lower(__first, __last, __val); return std::__lower_bound(__first, __last, __val, - __gnu_cxx::__ops::__iter_less_val()); + __gnu_cxx::__ops::less()); } /// This is a helper function for the sort routines and for random.tcc. @@ -1816,8 +1825,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first2, __last2); return std::__lexicographical_compare_impl - (__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); + (__first1, __last1, __first2, __last2, __comp); } #if __cpp_lib_three_way_comparison @@ -1925,7 +1933,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __mismatch(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, _BinaryPredicate __binary_pred) { - while (__first1 != __last1 && __binary_pred(__first1, __first2)) + while (__first1 != __last1 && __binary_pred(*__first1, *__first2)) { ++__first1; ++__first2; @@ -1961,7 +1969,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first1, __last1); return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, - __gnu_cxx::__ops::__iter_equal_to_iter()); + __gnu_cxx::__ops::equal_to()); } /** @@ -1993,7 +2001,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first1, __last1); return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, - __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); + __binary_pred); } #if __glibcxx_robust_nonmodifying_seq_ops // C++ >= 14 @@ -2006,7 +2014,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO _BinaryPredicate __binary_pred) { while (__first1 != __last1 && __first2 != __last2 - && __binary_pred(__first1, __first2)) + && __binary_pred(*__first1, *__first2)) { ++__first1; ++__first2; @@ -2044,7 +2052,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first2, __last2); return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_equal_to_iter()); + __gnu_cxx::__ops::equal_to()); } /** @@ -2079,9 +2087,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first2, __last2); return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); + __binary_pred); } -#endif +#endif // __glibcxx_robust_nonmodifying_seq_ops _GLIBCXX_END_NAMESPACE_ALGO @@ -2092,7 +2100,7 @@ _GLIBCXX_END_NAMESPACE_ALGO __find_if(_Iterator __first, _Iterator __last, _Predicate __pred) { #pragma GCC unroll 4 - while (__first != __last && !__pred(__first)) + while (__first != __last && !__pred(*__first)) ++__first; return __first; } @@ -2104,7 +2112,7 @@ _GLIBCXX_END_NAMESPACE_ALGO { typename iterator_traits<_InputIterator>::difference_type __n = 0; for (; __first != __last; ++__first) - if (__pred(__first)) + if (__pred(*__first)) ++__n; return __n; } @@ -2121,7 +2129,7 @@ _GLIBCXX_END_NAMESPACE_ALGO _ForwardIterator __result = __first; ++__first; for (; __first != __last; ++__first) - if (!__pred(__first)) + if (!__pred(*__first)) { *__result = _GLIBCXX_MOVE(*__first); ++__result; @@ -2141,20 +2149,21 @@ _GLIBCXX_END_NAMESPACE_ALGO if (__first1 == __last1 || __first2 == __last2) return __first1; + __decltype(*__first2) __first2_val(*__first2); + __decltype(__gnu_cxx::__ops::bind2nd(__predicate, __first2_val)) + __match_first = __gnu_cxx::__ops::bind2nd(__predicate, __first2_val); + // Test for a pattern of length 1. _ForwardIterator2 __p1(__first2); if (++__p1 == __last2) - return std::__find_if(__first1, __last1, - __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2)); + return std::__find_if(__first1, __last1, __match_first); // General case. _ForwardIterator1 __current = __first1; for (;;) { - __first1 = - std::__find_if(__first1, __last1, - __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2)); + __first1 = std::__find_if(__first1, __last1, __match_first); if (__first1 == __last1) return __last1; @@ -2164,7 +2173,7 @@ _GLIBCXX_END_NAMESPACE_ALGO if (++__current == __last1) return __last1; - while (__predicate(__current, __p)) + while (__predicate(*__current, *__p)) { if (++__p == __last2) return __first1; @@ -2175,6 +2184,7 @@ _GLIBCXX_END_NAMESPACE_ALGO } return __first1; } +#undef __match_first #if __cplusplus >= 201103L template<typename _ForwardIterator1, typename _ForwardIterator2, @@ -2187,7 +2197,7 @@ _GLIBCXX_END_NAMESPACE_ALGO // Efficiently compare identical prefixes: O(N) if sequences // have the same elements in the same order. for (; __first1 != __last1; ++__first1, (void)++__first2) - if (!__pred(__first1, __first2)) + if (!__pred(*__first1, *__first2)) break; if (__first1 == __last1) @@ -2199,17 +2209,14 @@ _GLIBCXX_END_NAMESPACE_ALGO std::advance(__last2, std::distance(__first1, __last1)); for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan) { - if (__scan != std::__find_if(__first1, __scan, - __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))) + auto&& __scan_val = *__scan; + auto __scaneq = __gnu_cxx::__ops::bind1st(__pred, __scan_val); + if (__scan != std::__find_if(__first1, __scan, __scaneq)) continue; // We've seen this one before. - auto __matches - = std::__count_if(__first2, __last2, - __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)); - if (0 == __matches || - std::__count_if(__scan, __last1, - __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)) - != __matches) + auto __matches = std::__count_if(__first2, __last2, __scaneq); + if (0 == __matches + || std::__count_if(__scan, __last1, __scaneq) != __matches) return false; } return true; @@ -2242,7 +2249,7 @@ _GLIBCXX_END_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first1, __last1); return std::__is_permutation(__first1, __last1, __first2, - __gnu_cxx::__ops::__iter_equal_to_iter()); + __gnu_cxx::__ops::equal_to()); } #endif // C++11 @@ -2286,8 +2293,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO __glibcxx_requires_valid_range(__first1, __last1); __glibcxx_requires_valid_range(__first2, __last2); - return std::__search(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_comp_iter(__predicate)); + return std::__search(__first1, __last1, __first2, __last2, __predicate); } _GLIBCXX_END_NAMESPACE_ALGO diff --git a/libstdc++-v3/include/bits/stl_construct.h b/libstdc++-v3/include/bits/stl_construct.h index 23b8fb7..98b403c 100644 --- a/libstdc++-v3/include/bits/stl_construct.h +++ b/libstdc++-v3/include/bits/stl_construct.h @@ -82,7 +82,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if constexpr (__cplusplus > 201703L && is_array_v<_Tp>) { for (auto& __x : *__location) - std::destroy_at(std::__addressof(__x)); + std::destroy_at(std::addressof(__x)); } else __location->~_Tp(); @@ -123,7 +123,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Construct(_Tp* __p, _Args&&... __args) { #if __cpp_constexpr_dynamic_alloc // >= C++20 - if (std::__is_constant_evaluated()) + if (std::is_constant_evaluated()) { // Allow std::_Construct to be used in constant expressions. std::construct_at(__p, std::forward<_Args>(__args)...); @@ -181,6 +181,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION for (; __first != __last; ++__first) std::_Destroy(std::__addressof(*__first)); } + + template<typename _ForwardIterator, typename _Size> + static _GLIBCXX20_CONSTEXPR _ForwardIterator + __destroy_n(_ForwardIterator __first, _Size __count) + { + for (; __count > 0; (void)++__first, --__count) + std::_Destroy(std::__addressof(*__first)); + return __first; + } }; template<> @@ -189,6 +198,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _ForwardIterator> static void __destroy(_ForwardIterator, _ForwardIterator) { } + + template<typename _ForwardIterator, typename _Size> + static _ForwardIterator + __destroy_n(_ForwardIterator __first, _Size __count) + { + std::advance(__first, __count); + return __first; + } }; #endif @@ -204,16 +221,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef typename iterator_traits<_ForwardIterator>::value_type _Value_type; #if __cplusplus >= 201103L - // A deleted destructor is trivial, this ensures we reject such types: - static_assert(is_destructible<_Value_type>::value, - "value type is destructible"); - if constexpr (!__has_trivial_destructor(_Value_type)) + if constexpr (!is_trivially_destructible<_Value_type>::value) for (; __first != __last; ++__first) - std::_Destroy(std::__addressof(*__first)); + std::_Destroy(std::addressof(*__first)); #if __cpp_constexpr_dynamic_alloc // >= C++20 - else if (std::__is_constant_evaluated()) + else if (std::is_constant_evaluated()) for (; __first != __last; ++__first) - std::destroy_at(std::__addressof(*__first)); + std::destroy_at(std::addressof(*__first)); #endif #else std::_Destroy_aux<__has_trivial_destructor(_Value_type)>:: @@ -221,33 +235,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif } -#if __cplusplus < 201103L - template<bool> - struct _Destroy_n_aux - { - template<typename _ForwardIterator, typename _Size> - static _GLIBCXX20_CONSTEXPR _ForwardIterator - __destroy_n(_ForwardIterator __first, _Size __count) - { - for (; __count > 0; (void)++__first, --__count) - std::_Destroy(std::__addressof(*__first)); - return __first; - } - }; - - template<> - struct _Destroy_n_aux<true> - { - template<typename _ForwardIterator, typename _Size> - static _ForwardIterator - __destroy_n(_ForwardIterator __first, _Size __count) - { - std::advance(__first, __count); - return __first; - } - }; -#endif - /** * Destroy a range of objects. If the value_type of the object has * a trivial destructor, the compiler should optimize all of this @@ -260,22 +247,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef typename iterator_traits<_ForwardIterator>::value_type _Value_type; #if __cplusplus >= 201103L - // A deleted destructor is trivial, this ensures we reject such types: - static_assert(is_destructible<_Value_type>::value, - "value type is destructible"); - if constexpr (!__has_trivial_destructor(_Value_type)) + if constexpr (!is_trivially_destructible<_Value_type>::value) for (; __count > 0; (void)++__first, --__count) - std::_Destroy(std::__addressof(*__first)); + std::_Destroy(std::addressof(*__first)); #if __cpp_constexpr_dynamic_alloc // >= C++20 - else if (std::__is_constant_evaluated()) + else if (std::is_constant_evaluated()) for (; __count > 0; (void)++__first, --__count) - std::destroy_at(std::__addressof(*__first)); + std::destroy_at(std::addressof(*__first)); #endif else std::advance(__first, __count); return __first; #else - return std::_Destroy_n_aux<__has_trivial_destructor(_Value_type)>:: + return std::_Destroy_aux<__has_trivial_destructor(_Value_type)>:: __destroy_n(__first, __count); #endif } @@ -297,6 +281,129 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #endif // C++17 +#if __glibcxx_start_lifetime_as >= 202207L // C++ >= 23 + template<typename _Tp> + [[__gnu__::__always_inline__]] + inline _Tp* + start_lifetime_as(void* __p) noexcept + { +#if __glibcxx_is_implicit_lifetime >= 202302L + static_assert(is_implicit_lifetime_v<_Tp>); +#endif + auto __q = reinterpret_cast<_Tp*>(__p); + __asm__ __volatile__("" : "=g" (__q), "=m" (*__q) + : "0" (__q), "m" (*__q)); + return __q; + } + + template<typename _Tp> + [[__gnu__::__always_inline__]] + inline const _Tp* + start_lifetime_as(const void* __p) noexcept + { +#if __glibcxx_is_implicit_lifetime >= 202302L + static_assert(is_implicit_lifetime_v<_Tp>); +#endif + auto __q = reinterpret_cast<const _Tp*>(__p); + auto __r = reinterpret_cast<_Tp*>(const_cast<void*>(__p)); + __asm__ __volatile__("" : "=g" (__q), "=m" (*__r) + : "0" (__q), "m" (*__q)); + return __q; + } + + template<typename _Tp> + [[__gnu__::__always_inline__]] + inline volatile _Tp* + start_lifetime_as(volatile void* __p) noexcept + { +#if __glibcxx_is_implicit_lifetime >= 202302L + static_assert(is_implicit_lifetime_v<_Tp>); +#endif + auto __q = reinterpret_cast<volatile _Tp*>(__p); + auto __r = reinterpret_cast<_Tp*>(const_cast<void*>(__p)); + __asm__ __volatile__("" : "=g" (__q), "=m" (*__r) + : "0" (__q), "m" (*__q)); + return __q; + } + + template<typename _Tp> + [[__gnu__::__always_inline__]] + inline const volatile _Tp* + start_lifetime_as(const volatile void* __p) noexcept + { +#if __glibcxx_is_implicit_lifetime >= 202302L + static_assert(is_implicit_lifetime_v<_Tp>); +#endif + auto __q = reinterpret_cast<const volatile _Tp*>(__p); + auto __r = reinterpret_cast<_Tp*>(const_cast<void*>(__p)); + __asm__ __volatile__("" : "=g" (__q), "=m" (*__r) + : "0" (__q), "m" (*__q)); + return __q; + } + + template<typename _Tp> + [[__gnu__::__always_inline__]] + inline _Tp* + start_lifetime_as_array(void* __p, size_t __n) noexcept + { + auto __q = reinterpret_cast<_Tp*>(__p); + if (!__n) + return __q; + auto __r = (__extension__ reinterpret_cast<_Tp(*)[__n]>(__p)); + __asm__ __volatile__("" : "=g" (__q), "=m" (*__r) + : "0" (__q), "m" (*__r)); + return __q; + } + + template<typename _Tp> + [[__gnu__::__always_inline__]] + inline const _Tp* + start_lifetime_as_array(const void* __p, size_t __n) noexcept + { + auto __q = reinterpret_cast<const _Tp*>(__p); + if (!__n) + return __q; + auto __r = (__extension__ reinterpret_cast<const _Tp(*)[__n]>(__p)); + auto __s = (__extension__ + reinterpret_cast<_Tp(*)[__n]>(const_cast<void*>(__p))); + __asm__ __volatile__("" : "=g" (__q), "=m" (*__s) + : "0" (__q), "m" (*__r)); + return __q; + } + + template<typename _Tp> + [[__gnu__::__always_inline__]] + inline volatile _Tp* + start_lifetime_as_array(volatile void* __p, size_t __n) noexcept + { + auto __q = reinterpret_cast<volatile _Tp*>(__p); + if (!__n) + return __q; + auto __r = (__extension__ reinterpret_cast<volatile _Tp(*)[__n]>(__p)); + auto __s = (__extension__ + reinterpret_cast<_Tp(*)[__n]>(const_cast<void*>(__p))); + __asm__ __volatile__("" : "=g" (__q), "=m" (*__s) + : "0" (__q), "m" (*__r)); + return __q; + } + + template<typename _Tp> + [[__gnu__::__always_inline__]] + inline const volatile _Tp* + start_lifetime_as_array(const volatile void* __p, size_t __n) noexcept + { + auto __q = reinterpret_cast<const volatile _Tp*>(__p); + if (!__n) + return __q; + auto __r = (__extension__ reinterpret_cast<const volatile _Tp(*)[__n]>(__p)); + auto __s = (__extension__ + reinterpret_cast<_Tp(*)[__n]>(const_cast<void*>(__p))); + __asm__ __volatile__("" : "=g" (__q), "=m" (*__s) + : "0" (__q), "m" (*__r)); + return __q; + } +#endif // C++23 + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/stl_deque.h b/libstdc++-v3/include/bits/stl_deque.h index 8d8ee57..7cc711e 100644 --- a/libstdc++-v3/include/bits/stl_deque.h +++ b/libstdc++-v3/include/bits/stl_deque.h @@ -1331,7 +1331,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { size_type __sz = this->_M_impl._M_finish - this->_M_impl._M_start; if (__sz > max_size ()) - __builtin_unreachable (); + __builtin_unreachable(); return __sz; } @@ -2163,6 +2163,35 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER iterator _M_insert_aux(iterator __pos, const value_type& __x); #else + struct _Temporary_value + { + template<typename... _Args> + _GLIBCXX20_CONSTEXPR explicit + _Temporary_value(deque* __deque, _Args&&... __args) : _M_this(__deque) + { + _Alloc_traits::construct(_M_this->_M_impl, _M_ptr(), + std::forward<_Args>(__args)...); + } + + _GLIBCXX20_CONSTEXPR + ~_Temporary_value() + { _Alloc_traits::destroy(_M_this->_M_impl, _M_ptr()); } + + _GLIBCXX20_CONSTEXPR value_type& + _M_val() noexcept { return __tmp_val; } + + private: + _GLIBCXX20_CONSTEXPR _Tp* + _M_ptr() noexcept { return std::__addressof(__tmp_val); } + + union + { + _Tp __tmp_val; + }; + + deque* _M_this; + }; + iterator _M_insert_aux(iterator __pos, const value_type& __x) { return _M_emplace_aux(__pos, __x); } diff --git a/libstdc++-v3/include/bits/stl_function.h b/libstdc++-v3/include/bits/stl_function.h index 136fd01..ff3f8f4 100644 --- a/libstdc++-v3/include/bits/stl_function.h +++ b/libstdc++-v3/include/bits/stl_function.h @@ -762,6 +762,58 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION is_convertible<_Tp, const volatile void*>, is_convertible<_Up, const volatile void*>>; }; +#else // < C++14 + + // We need less<void> and equal_to<void> for <bits/predefined_ops.h> + + template<> + struct equal_to<void> + { +#ifdef __cpp_rvalue_references + template<typename _Tp, typename _Up> + bool + operator()(_Tp&& __t, _Up&& __u) const + { return __t == __u; } +#else // C++98 + template<typename _Tp, typename _Up> + bool + operator()(_Tp& __t, _Up& __u) const { return __t == __u; } + template<typename _Tp, typename _Up> + bool + operator()(const _Tp& __t, _Up& __u) const { return __t == __u; } + template<typename _Tp, typename _Up> + bool + operator()(_Tp& __t, const _Up& __u) const { return __t == __u; } + template<typename _Tp, typename _Up> + bool + operator()(const _Tp& __t, const _Up& __u) const { return __t == __u; } +#endif + }; + + template<> + struct less<void> + { +#ifdef __cpp_rvalue_references + template<typename _Tp, typename _Up> + bool + operator()(_Tp&& __t, _Up&& __u) const + { return __t < __u; } +#else // C++98 + template<typename _Tp, typename _Up> + bool + operator()(_Tp& __t, _Up& __u) const { return __t < __u; } + template<typename _Tp, typename _Up> + bool + operator()(const _Tp& __t, _Up& __u) const { return __t < __u; } + template<typename _Tp, typename _Up> + bool + operator()(_Tp& __t, const _Up& __u) const { return __t < __u; } + template<typename _Tp, typename _Up> + bool + operator()(const _Tp& __t, const _Up& __u) const { return __t < __u; } +#endif + }; + #endif // __glibcxx_transparent_operators /** @} */ diff --git a/libstdc++-v3/include/bits/stl_heap.h b/libstdc++-v3/include/bits/stl_heap.h index 028ac83..b10495b 100644 --- a/libstdc++-v3/include/bits/stl_heap.h +++ b/libstdc++-v3/include/bits/stl_heap.h @@ -76,10 +76,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __is_heap_until(_RandomAccessIterator __first, _Distance __n, _Compare& __comp) { +#if __cplusplus >= 201103L + using _IterTraits = iterator_traits<_RandomAccessIterator>; + static_assert(is_same<typename _IterTraits::difference_type, + _Distance>::value, + "Argument 'n' must be the iterator's difference type"); +#endif _Distance __parent = 0; for (_Distance __child = 1; __child < __n; ++__child) { - if (__comp(__first + __parent, __first + __child)) + if (__comp(__first[__parent], __first[__child])) return __child; if ((__child & 1) == 0) ++__parent; @@ -94,8 +100,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline bool __is_heap(_RandomAccessIterator __first, _Distance __n) { - __gnu_cxx::__ops::_Iter_less_iter __comp; - return std::__is_heap_until(__first, __n, __comp) == __n; + typename iterator_traits<_RandomAccessIterator>::difference_type __d(__n); + __gnu_cxx::__ops::less __comp; + return std::__is_heap_until(__first, __d, __comp) == __n; } template<typename _RandomAccessIterator, typename _Compare, @@ -104,9 +111,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline bool __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n) { - typedef __decltype(__comp) _Cmp; - __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); - return std::__is_heap_until(__first, __n, __cmp) == __n; + typename iterator_traits<_RandomAccessIterator>::difference_type __d(__n); + return std::__is_heap_until(__first, __d, __comp) == __n; } template<typename _RandomAccessIterator> @@ -137,7 +143,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Compare& __comp) { _Distance __parent = (__holeIndex - 1) / 2; - while (__holeIndex > __topIndex && __comp(__first + __parent, __value)) + while (__holeIndex > __topIndex && __comp(__first[__parent], __value)) { *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent)); __holeIndex = __parent; @@ -172,10 +178,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>) __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive(__first, __last); - __glibcxx_requires_heap(__first, __last - 1); + __glibcxx_requires_heap(__first, __last - _DistanceType(1)); - __gnu_cxx::__ops::_Iter_less_val __comp; - _ValueType __value = _GLIBCXX_MOVE(*(__last - 1)); + __gnu_cxx::__ops::less __comp; + _ValueType __value = _GLIBCXX_MOVE(*(__last - _DistanceType(1))); std::__push_heap(__first, _DistanceType((__last - __first) - 1), _DistanceType(0), _GLIBCXX_MOVE(__value), __comp); } @@ -208,13 +214,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _RandomAccessIterator>) __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - __glibcxx_requires_heap_pred(__first, __last - 1, __comp); + __glibcxx_requires_heap_pred(__first, __last - _DistanceType(1), __comp); - __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp))) - __cmp(_GLIBCXX_MOVE(__comp)); - _ValueType __value = _GLIBCXX_MOVE(*(__last - 1)); + _ValueType __value = _GLIBCXX_MOVE(*(__last - _DistanceType(1))); std::__push_heap(__first, _DistanceType((__last - __first) - 1), - _DistanceType(0), _GLIBCXX_MOVE(__value), __cmp); + _DistanceType(0), _GLIBCXX_MOVE(__value), __comp); } template<typename _RandomAccessIterator, typename _Distance, @@ -229,8 +233,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION while (__secondChild < (__len - 1) / 2) { __secondChild = 2 * (__secondChild + 1); - if (__comp(__first + __secondChild, - __first + (__secondChild - 1))) + if (__comp(__first[__secondChild], + __first[__secondChild - 1])) __secondChild--; *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild)); __holeIndex = __secondChild; @@ -242,10 +246,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION + (__secondChild - 1))); __holeIndex = __secondChild - 1; } - __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp))) - __cmp(_GLIBCXX_MOVE(__comp)); std::__push_heap(__first, __holeIndex, __topIndex, - _GLIBCXX_MOVE(__value), __cmp); + _GLIBCXX_MOVE(__value), __comp); } template<typename _RandomAccessIterator, typename _Compare> @@ -295,7 +297,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__last - __first > 1) { --__last; - __gnu_cxx::__ops::_Iter_less_iter __comp; + __gnu_cxx::__ops::less __comp; std::__pop_heap(__first, __last, __last, __comp); } } @@ -327,10 +329,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__last - __first > 1) { - typedef __decltype(__comp) _Cmp; - __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); --__last; - std::__pop_heap(__first, __last, __last, __cmp); + std::__pop_heap(__first, __last, __last, __comp); } } @@ -382,7 +382,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive(__first, __last); - __gnu_cxx::__ops::_Iter_less_iter __comp; + __gnu_cxx::__ops::less __comp; std::__make_heap(__first, __last, __comp); } @@ -408,9 +408,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - typedef __decltype(__comp) _Cmp; - __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); - std::__make_heap(__first, __last, __cmp); + std::__make_heap(__first, __last, __comp); } template<typename _RandomAccessIterator, typename _Compare> @@ -448,7 +446,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_irreflexive(__first, __last); __glibcxx_requires_heap(__first, __last); - __gnu_cxx::__ops::_Iter_less_iter __comp; + __gnu_cxx::__ops::less __comp; std::__sort_heap(__first, __last, __comp); } @@ -475,9 +473,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_irreflexive_pred(__first, __last, __comp); __glibcxx_requires_heap_pred(__first, __last, __comp); - typedef __decltype(__comp) _Cmp; - __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); - std::__sort_heap(__first, __last, __cmp); + std::__sort_heap(__first, __last, __comp); } #if __cplusplus >= 201103L @@ -504,7 +500,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive(__first, __last); - __gnu_cxx::__ops::_Iter_less_iter __comp; + __gnu_cxx::__ops::less __comp; return __first + std::__is_heap_until(__first, std::distance(__first, __last), __comp); } @@ -532,10 +528,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_valid_range(__first, __last); __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - typedef __decltype(__comp) _Cmp; - __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); return __first - + std::__is_heap_until(__first, std::distance(__first, __last), __cmp); + + std::__is_heap_until(__first, std::distance(__first, __last), + __comp); } /** @@ -572,9 +567,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __glibcxx_requires_irreflexive_pred(__first, __last, __comp); const auto __dist = std::distance(__first, __last); - typedef __decltype(__comp) _Cmp; - __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); - return std::__is_heap_until(__first, __dist, __cmp) == __dist; + return std::__is_heap_until(__first, __dist, __comp) == __dist; } #endif diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index 478a98f..75e794f 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -1164,188 +1164,201 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const _Iterator& base() const _GLIBCXX_NOEXCEPT { return _M_current; } - }; - // Note: In what follows, the left- and right-hand-side iterators are - // allowed to vary in types (conceptually in cv-qualification) so that - // comparison between cv-qualified and non-cv-qualified iterators be - // valid. However, the greedy and unfriendly operators in std::rel_ops - // will make overload resolution ambiguous (when in scope) if we don't - // provide overloads whose operands are of the same type. Can someone - // remind me what generic programming is about? -- Gaby + private: + // Note: In what follows, the left- and right-hand-side iterators are + // allowed to vary in types (conceptually in cv-qualification) so that + // comparison between cv-qualified and non-cv-qualified iterators be + // valid. However, the greedy and unfriendly operators in std::rel_ops + // will make overload resolution ambiguous (when in scope) if we don't + // provide overloads whose operands are of the same type. Can someone + // remind me what generic programming is about? -- Gaby #ifdef __cpp_lib_three_way_comparison - template<typename _IteratorL, typename _IteratorR, typename _Container> - [[nodiscard, __gnu__::__always_inline__]] - constexpr bool - operator==(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) - noexcept(noexcept(__lhs.base() == __rhs.base())) - requires requires { - { __lhs.base() == __rhs.base() } -> std::convertible_to<bool>; - } - { return __lhs.base() == __rhs.base(); } - - template<typename _IteratorL, typename _IteratorR, typename _Container> - [[nodiscard, __gnu__::__always_inline__]] - constexpr std::__detail::__synth3way_t<_IteratorR, _IteratorL> - operator<=>(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) - noexcept(noexcept(std::__detail::__synth3way(__lhs.base(), __rhs.base()))) - { return std::__detail::__synth3way(__lhs.base(), __rhs.base()); } + template<typename _Iter> + [[nodiscard, __gnu__::__always_inline__]] + friend + constexpr bool + operator==(const __normal_iterator& __lhs, + const __normal_iterator<_Iter, _Container>& __rhs) + noexcept(noexcept(__lhs.base() == __rhs.base())) + requires requires { + { __lhs.base() == __rhs.base() } -> std::convertible_to<bool>; + } + { return __lhs.base() == __rhs.base(); } - template<typename _Iterator, typename _Container> - [[nodiscard, __gnu__::__always_inline__]] - constexpr bool - operator==(const __normal_iterator<_Iterator, _Container>& __lhs, - const __normal_iterator<_Iterator, _Container>& __rhs) - noexcept(noexcept(__lhs.base() == __rhs.base())) - requires requires { - { __lhs.base() == __rhs.base() } -> std::convertible_to<bool>; - } - { return __lhs.base() == __rhs.base(); } + [[nodiscard, __gnu__::__always_inline__]] + friend + constexpr bool + operator==(const __normal_iterator& __lhs, const __normal_iterator& __rhs) + noexcept(noexcept(__lhs.base() == __rhs.base())) + requires requires { + { __lhs.base() == __rhs.base() } -> std::convertible_to<bool>; + } + { return __lhs.base() == __rhs.base(); } - template<typename _Iterator, typename _Container> - [[nodiscard, __gnu__::__always_inline__]] - constexpr std::__detail::__synth3way_t<_Iterator> - operator<=>(const __normal_iterator<_Iterator, _Container>& __lhs, - const __normal_iterator<_Iterator, _Container>& __rhs) - noexcept(noexcept(std::__detail::__synth3way(__lhs.base(), __rhs.base()))) - { return std::__detail::__synth3way(__lhs.base(), __rhs.base()); } + template<typename _Iter> + [[nodiscard, __gnu__::__always_inline__]] + friend + constexpr std::__detail::__synth3way_t<_Iterator, _Iter> + operator<=>(const __normal_iterator& __lhs, + const __normal_iterator<_Iter, _Container>& __rhs) + noexcept(noexcept(std::__detail::__synth3way(__lhs.base(), __rhs.base()))) + requires requires { + std::__detail::__synth3way(__lhs.base(), __rhs.base()); + } + { return std::__detail::__synth3way(__lhs.base(), __rhs.base()); } #else - // Forward iterator requirements - template<typename _IteratorL, typename _IteratorR, typename _Container> - _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR - inline bool - operator==(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() == __rhs.base(); } + // Forward iterator requirements + template<typename _Iter> + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) + friend + _GLIBCXX_CONSTEXPR + bool + operator==(const __normal_iterator& __lhs, + const __normal_iterator<_Iter, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() == __rhs.base(); } - template<typename _Iterator, typename _Container> - _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR - inline bool - operator==(const __normal_iterator<_Iterator, _Container>& __lhs, - const __normal_iterator<_Iterator, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() == __rhs.base(); } - - template<typename _IteratorL, typename _IteratorR, typename _Container> - _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR - inline bool - operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() != __rhs.base(); } + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) + friend + _GLIBCXX_CONSTEXPR + bool + operator==(const __normal_iterator& __lhs, const __normal_iterator& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() == __rhs.base(); } - template<typename _Iterator, typename _Container> - _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR - inline bool - operator!=(const __normal_iterator<_Iterator, _Container>& __lhs, - const __normal_iterator<_Iterator, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() != __rhs.base(); } - - // Random access iterator requirements - template<typename _IteratorL, typename _IteratorR, typename _Container> - _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR - inline bool - operator<(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() < __rhs.base(); } + template<typename _Iter> + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) + friend + _GLIBCXX_CONSTEXPR + bool + operator!=(const __normal_iterator& __lhs, + const __normal_iterator<_Iter, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() != __rhs.base(); } - template<typename _Iterator, typename _Container> - _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR - inline bool - operator<(const __normal_iterator<_Iterator, _Container>& __lhs, - const __normal_iterator<_Iterator, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() < __rhs.base(); } - - template<typename _IteratorL, typename _IteratorR, typename _Container> - _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR - inline bool - operator>(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() > __rhs.base(); } + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) + friend + _GLIBCXX_CONSTEXPR + bool + operator!=(const __normal_iterator& __lhs, const __normal_iterator& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() != __rhs.base(); } - template<typename _Iterator, typename _Container> - _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR - inline bool - operator>(const __normal_iterator<_Iterator, _Container>& __lhs, - const __normal_iterator<_Iterator, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() > __rhs.base(); } - - template<typename _IteratorL, typename _IteratorR, typename _Container> - _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR - inline bool - operator<=(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() <= __rhs.base(); } + // Random access iterator requirements + template<typename _Iter> + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) + friend + _GLIBCXX_CONSTEXPR + inline bool + operator<(const __normal_iterator& __lhs, + const __normal_iterator<_Iter, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() < __rhs.base(); } - template<typename _Iterator, typename _Container> - _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR - inline bool - operator<=(const __normal_iterator<_Iterator, _Container>& __lhs, - const __normal_iterator<_Iterator, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() <= __rhs.base(); } - - template<typename _IteratorL, typename _IteratorR, typename _Container> - _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR - inline bool - operator>=(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() >= __rhs.base(); } + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) + friend + _GLIBCXX20_CONSTEXPR + bool + operator<(const __normal_iterator& __lhs, const __normal_iterator& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() < __rhs.base(); } - template<typename _Iterator, typename _Container> - _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR - inline bool - operator>=(const __normal_iterator<_Iterator, _Container>& __lhs, - const __normal_iterator<_Iterator, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() >= __rhs.base(); } + template<typename _Iter> + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) + friend + _GLIBCXX_CONSTEXPR + bool + operator>(const __normal_iterator& __lhs, + const __normal_iterator<_Iter, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() > __rhs.base(); } + + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) + friend + _GLIBCXX_CONSTEXPR + bool + operator>(const __normal_iterator& __lhs, const __normal_iterator& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() > __rhs.base(); } + + template<typename _Iter> + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) + friend + _GLIBCXX_CONSTEXPR + bool + operator<=(const __normal_iterator& __lhs, + const __normal_iterator<_Iter, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() <= __rhs.base(); } + + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) + friend + _GLIBCXX_CONSTEXPR + bool + operator<=(const __normal_iterator& __lhs, const __normal_iterator& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() <= __rhs.base(); } + + template<typename _Iter> + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) + friend + _GLIBCXX_CONSTEXPR + bool + operator>=(const __normal_iterator& __lhs, + const __normal_iterator<_Iter, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() >= __rhs.base(); } + + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) + friend + _GLIBCXX_CONSTEXPR + bool + operator>=(const __normal_iterator& __lhs, const __normal_iterator& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() >= __rhs.base(); } #endif // three-way comparison - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // According to the resolution of DR179 not only the various comparison - // operators but also operator- must accept mixed iterator/const_iterator - // parameters. - template<typename _IteratorL, typename _IteratorR, typename _Container> + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 179. Comparison of const_iterators to iterators doesn't work + // According to the resolution of DR179 not only the various comparison + // operators but also operator- must accept mixed iterator/const_iterator + // parameters. + template<typename _Iter> #if __cplusplus >= 201103L - // DR 685. - [[__nodiscard__, __gnu__::__always_inline__]] - constexpr auto - operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) noexcept - -> decltype(__lhs.base() - __rhs.base()) + [[__nodiscard__, __gnu__::__always_inline__]] + friend + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 685. reverse_iterator/move_iterator difference has invalid signatures + constexpr auto + operator-(const __normal_iterator& __lhs, + const __normal_iterator<_Iter, _Container>& __rhs) noexcept + -> decltype(__lhs.base() - __rhs.base()) #else - inline typename __normal_iterator<_IteratorL, _Container>::difference_type - operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) + friend + difference_type + operator-(const __normal_iterator& __lhs, + const __normal_iterator<_Iter, _Container>& __rhs) #endif - { return __lhs.base() - __rhs.base(); } + { return __lhs.base() - __rhs.base(); } - template<typename _Iterator, typename _Container> - _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR - inline typename __normal_iterator<_Iterator, _Container>::difference_type - operator-(const __normal_iterator<_Iterator, _Container>& __lhs, - const __normal_iterator<_Iterator, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() - __rhs.base(); } + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) + friend + _GLIBCXX_CONSTEXPR + difference_type + operator-(const __normal_iterator& __lhs, const __normal_iterator& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() - __rhs.base(); } - template<typename _Iterator, typename _Container> - _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR - inline __normal_iterator<_Iterator, _Container> - operator+(typename __normal_iterator<_Iterator, _Container>::difference_type - __n, const __normal_iterator<_Iterator, _Container>& __i) - _GLIBCXX_NOEXCEPT - { return __normal_iterator<_Iterator, _Container>(__i.base() + __n); } + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) + friend + _GLIBCXX_CONSTEXPR + __normal_iterator + operator+(difference_type __n, const __normal_iterator& __i) + _GLIBCXX_NOEXCEPT + { return __normal_iterator(__i.base() + __n); } + }; _GLIBCXX_END_NAMESPACE_VERSION } // namespace __gnu_cxx diff --git a/libstdc++-v3/include/bits/stl_iterator_base_funcs.h b/libstdc++-v3/include/bits/stl_iterator_base_funcs.h index 637159f..7c80e14 100644 --- a/libstdc++-v3/include/bits/stl_iterator_base_funcs.h +++ b/libstdc++-v3/include/bits/stl_iterator_base_funcs.h @@ -130,6 +130,28 @@ _GLIBCXX_END_NAMESPACE_CONTAINER __distance(_OutputIterator, _OutputIterator, output_iterator_tag) = delete; #endif +#ifdef __glibcxx_concepts +namespace __detail +{ + // Satisfied if ITER_TRAITS(Iter)::iterator_category is valid and is + // at least as strong as ITER_TRAITS(Iter)::iterator_concept. + template<typename _Iter> + concept __iter_category_converts_to_concept + = convertible_to<typename __iter_traits<_Iter>::iterator_category, + typename __iter_traits<_Iter>::iterator_concept>; + + // Satisfied if the type is a C++20 iterator that defines iterator_concept, + // and its iterator_concept is stronger than its iterator_category (if any). + // Used by std::distance and std::advance to detect iterators which should + // dispatch based on their C++20 concept not their C++17 category. + template<typename _Iter> + concept __promotable_iterator + = input_iterator<_Iter> + && requires { typename __iter_traits<_Iter>::iterator_concept; } + && ! __iter_category_converts_to_concept<_Iter>; +} // namespace __detail +#endif + /** * @brief A generalization of pointer arithmetic. * @param __first An input iterator. @@ -149,6 +171,24 @@ _GLIBCXX_END_NAMESPACE_CONTAINER typename iterator_traits<_InputIterator>::difference_type distance(_InputIterator __first, _InputIterator __last) { +#ifdef __glibcxx_concepts + // A type which satisfies the C++20 random_access_iterator concept might + // have input_iterator_tag as its iterator_category type, which would + // mean we select the O(n) __distance. Or a C++20 std::input_iterator + // that is not a Cpp17InputIterator might have output_iterator_tag as + // its iterator_category type and then calling __distance with + // std::__iterator_category(__first) would be ill-formed. + // So for C++20 iterator types we can just choose to do the right thing. + if constexpr (__detail::__promotable_iterator<_InputIterator>) + { + if constexpr (random_access_iterator<_InputIterator>) + return __last - __first; + else + return std::__distance(std::move(__first), std::move(__last), + input_iterator_tag()); + } + else // assume it meets the Cpp17InputIterator requirements: +#endif // concept requirements -- taken care of in __distance return std::__distance(__first, __last, std::__iterator_category(__first)); @@ -161,7 +201,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER // concept requirements __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) __glibcxx_assert(__n >= 0); - while (__n--) + while (__n-- > 0) ++__i; } @@ -221,9 +261,31 @@ _GLIBCXX_END_NAMESPACE_CONTAINER inline _GLIBCXX17_CONSTEXPR void advance(_InputIterator& __i, _Distance __n) { - // concept requirements -- taken care of in __advance - typename iterator_traits<_InputIterator>::difference_type __d = __n; - std::__advance(__i, __d, std::__iterator_category(__i)); +#ifdef __glibcxx_concepts + // A type which satisfies the C++20 bidirectional_iterator concept might + // have input_iterator_tag as its iterator_category type, which would + // mean we select the __advance overload which cannot move backwards. + // For a C++20 random_access_iterator we might select the O(n) __advance + // if it doesn't meet the Cpp17RandomAccessIterator requirements. + // So for C++20 iterator types we can just choose to do the right thing. + if constexpr (__detail::__promotable_iterator<_InputIterator> + && ranges::__detail::__is_integer_like<_Distance>) + { + auto __d = static_cast<iter_difference_t<_InputIterator>>(__n); + if constexpr (random_access_iterator<_InputIterator>) + std::__advance(__i, __d, random_access_iterator_tag()); + else if constexpr (bidirectional_iterator<_InputIterator>) + std::__advance(__i, __d, bidirectional_iterator_tag()); + else + std::__advance(__i, __d, input_iterator_tag()); + } + else // assume it meets the Cpp17InputIterator requirements: +#endif + { + // concept requirements -- taken care of in __advance + typename iterator_traits<_InputIterator>::difference_type __d = __n; + std::__advance(__i, __d, std::__iterator_category(__i)); + } } #if __cplusplus >= 201103L diff --git a/libstdc++-v3/include/bits/stl_iterator_base_types.h b/libstdc++-v3/include/bits/stl_iterator_base_types.h index a67d7bd..0c34ad7 100644 --- a/libstdc++-v3/include/bits/stl_iterator_base_types.h +++ b/libstdc++-v3/include/bits/stl_iterator_base_types.h @@ -257,6 +257,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _InIter> concept __has_input_iter_cat = is_convertible_v<__iter_category_t<_InIter>, input_iterator_tag>; + +#ifdef __cpp_lib_concepts + // Is a Cpp17InputIterator or satisfies std::input_iterator. + template<typename _InIterator> + concept __any_input_iterator + = input_iterator<_InIterator> || __has_input_iter_cat<_InIterator>; +#endif #endif template<typename _It, diff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h index 68c23b8..62d66ce 100644 --- a/libstdc++-v3/include/bits/stl_map.h +++ b/libstdc++-v3/include/bits/stl_map.h @@ -1259,7 +1259,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER find(const key_type& __x) { return _M_t.find(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto find(const _Kt& __x) -> decltype(_M_t._M_find_tr(__x)) @@ -1284,7 +1284,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER find(const key_type& __x) const { return _M_t.find(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto find(const _Kt& __x) const -> decltype(_M_t._M_find_tr(__x)) @@ -1305,7 +1305,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER count(const key_type& __x) const { return _M_t.find(__x) == _M_t.end() ? 0 : 1; } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x)) @@ -1348,7 +1348,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER lower_bound(const key_type& __x) { return _M_t.lower_bound(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto lower_bound(const _Kt& __x) @@ -1373,7 +1373,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER lower_bound(const key_type& __x) const { return _M_t.lower_bound(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto lower_bound(const _Kt& __x) const @@ -1393,7 +1393,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER upper_bound(const key_type& __x) { return _M_t.upper_bound(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto upper_bound(const _Kt& __x) @@ -1413,7 +1413,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER upper_bound(const key_type& __x) const { return _M_t.upper_bound(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto upper_bound(const _Kt& __x) const @@ -1442,7 +1442,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER equal_range(const key_type& __x) { return _M_t.equal_range(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto equal_range(const _Kt& __x) @@ -1471,7 +1471,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER equal_range(const key_type& __x) const { return _M_t.equal_range(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto equal_range(const _Kt& __x) const @@ -1649,7 +1649,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER -#if __cplusplus > 201402L +#ifdef __glibcxx_node_extract // >= C++17 && HOSTED // Allow std::map access to internals of compatible maps. template<typename _Key, typename _Val, typename _Cmp1, typename _Alloc, typename _Cmp2> diff --git a/libstdc++-v3/include/bits/stl_multimap.h b/libstdc++-v3/include/bits/stl_multimap.h index 4ee4a84..b2ae2ba 100644 --- a/libstdc++-v3/include/bits/stl_multimap.h +++ b/libstdc++-v3/include/bits/stl_multimap.h @@ -891,7 +891,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER find(const key_type& __x) { return _M_t.find(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto find(const _Kt& __x) -> decltype(_M_t._M_find_tr(__x)) @@ -915,7 +915,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER find(const key_type& __x) const { return _M_t.find(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto find(const _Kt& __x) const -> decltype(_M_t._M_find_tr(__x)) @@ -933,7 +933,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER count(const key_type& __x) const { return _M_t.count(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x)) @@ -976,7 +976,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER lower_bound(const key_type& __x) { return _M_t.lower_bound(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto lower_bound(const _Kt& __x) @@ -1001,7 +1001,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER lower_bound(const key_type& __x) const { return _M_t.lower_bound(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto lower_bound(const _Kt& __x) const @@ -1021,7 +1021,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER upper_bound(const key_type& __x) { return _M_t.upper_bound(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto upper_bound(const _Kt& __x) @@ -1041,7 +1041,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER upper_bound(const key_type& __x) const { return _M_t.upper_bound(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto upper_bound(const _Kt& __x) const @@ -1068,7 +1068,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER equal_range(const key_type& __x) { return _M_t.equal_range(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto equal_range(const _Kt& __x) @@ -1095,7 +1095,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER equal_range(const key_type& __x) const { return _M_t.equal_range(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto equal_range(const _Kt& __x) const @@ -1272,7 +1272,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER -#if __cplusplus > 201402L +#ifdef __glibcxx_node_extract // >= C++17 && HOSTED // Allow std::multimap access to internals of compatible maps. template<typename _Key, typename _Val, typename _Cmp1, typename _Alloc, typename _Cmp2> diff --git a/libstdc++-v3/include/bits/stl_multiset.h b/libstdc++-v3/include/bits/stl_multiset.h index 31451ab..b6e1bfc 100644 --- a/libstdc++-v3/include/bits/stl_multiset.h +++ b/libstdc++-v3/include/bits/stl_multiset.h @@ -773,7 +773,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER count(const key_type& __x) const { return _M_t.count(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x)) @@ -822,7 +822,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER find(const key_type& __x) const { return _M_t.find(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto find(const _Kt& __x) @@ -857,7 +857,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER lower_bound(const key_type& __x) const { return _M_t.lower_bound(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto lower_bound(const _Kt& __x) @@ -887,7 +887,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER upper_bound(const key_type& __x) const { return _M_t.upper_bound(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto upper_bound(const _Kt& __x) @@ -926,7 +926,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER equal_range(const key_type& __x) const { return _M_t.equal_range(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto equal_range(const _Kt& __x) @@ -1103,7 +1103,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER -#if __cplusplus > 201402L +#ifdef __glibcxx_node_extract // >= C++17 && HOSTED // Allow std::multiset access to internals of compatible sets. template<typename _Val, typename _Cmp1, typename _Alloc, typename _Cmp2> struct diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index 8c57712..231d0bb 100644 --- a/libstdc++-v3/include/bits/stl_pair.h +++ b/libstdc++-v3/include/bits/stl_pair.h @@ -445,7 +445,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Constructor accepting lvalues of `first_type` and `second_type` constexpr explicit(!_S_convertible<const _T1&, const _T2&>()) - pair(const _T1& __x, const _T2& __y) + pair(const type_identity_t<_T1>& __x, const _T2& __y) noexcept(_S_nothrow_constructible<const _T1&, const _T2&>()) requires (_S_constructible<const _T1&, const _T2&>()) : first(__x), second(__y) @@ -1132,6 +1132,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif // C++23 #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2766. Swapping non-swappable types template<typename _T1, typename _T2> typename enable_if<!__and_<__is_swappable<_T1>, __is_swappable<_T2>>::value>::type @@ -1313,12 +1315,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template <typename _Tp, typename _Up> constexpr _Tp&& get(pair<_Tp, _Up>&& __p) noexcept - { return std::move(__p.first); } + { return std::forward<_Tp>(__p.first); } template <typename _Tp, typename _Up> constexpr const _Tp&& get(const pair<_Tp, _Up>&& __p) noexcept - { return std::move(__p.first); } + { return std::forward<const _Tp>(__p.first); } template <typename _Tp, typename _Up> constexpr _Tp& @@ -1333,12 +1335,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template <typename _Tp, typename _Up> constexpr _Tp&& get(pair<_Up, _Tp>&& __p) noexcept - { return std::move(__p.second); } + { return std::forward<_Tp>(__p.second); } template <typename _Tp, typename _Up> constexpr const _Tp&& get(const pair<_Up, _Tp>&& __p) noexcept - { return std::move(__p.second); } + { return std::forward<const _Tp>(__p.second); } #endif // __glibcxx_tuples_by_type diff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h index b65d631..f03d9e5 100644 --- a/libstdc++-v3/include/bits/stl_set.h +++ b/libstdc++-v3/include/bits/stl_set.h @@ -794,7 +794,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER count(const key_type& __x) const { return _M_t.find(__x) == _M_t.end() ? 0 : 1; } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto count(const _Kt& __x) const @@ -844,7 +844,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER find(const key_type& __x) const { return _M_t.find(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto find(const _Kt& __x) @@ -879,7 +879,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER lower_bound(const key_type& __x) const { return _M_t.lower_bound(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto lower_bound(const _Kt& __x) @@ -909,7 +909,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER upper_bound(const key_type& __x) const { return _M_t.upper_bound(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto upper_bound(const _Kt& __x) @@ -948,7 +948,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER equal_range(const key_type& __x) const { return _M_t.equal_range(__x); } -#if __cplusplus > 201103L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt> auto equal_range(const _Kt& __x) @@ -1119,7 +1119,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER -#if __cplusplus > 201402L +#ifdef __glibcxx_node_extract // >= C++17 && HOSTED // Allow std::set access to internals of compatible sets. template<typename _Val, typename _Cmp1, typename _Alloc, typename _Cmp2> struct diff --git a/libstdc++-v3/include/bits/stl_tempbuf.h b/libstdc++-v3/include/bits/stl_tempbuf.h index 7a7619e..8cc7b11 100644 --- a/libstdc++-v3/include/bits/stl_tempbuf.h +++ b/libstdc++-v3/include/bits/stl_tempbuf.h @@ -227,7 +227,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// Returns the size requested by the constructor; may be >size(). size_type - requested_size() const + _M_requested_size() const { return _M_original_len; } /// As per Table mumble. diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h index 4b7f482..e78fa1d 100644 --- a/libstdc++-v3/include/bits/stl_tree.h +++ b/libstdc++-v3/include/bits/stl_tree.h @@ -1918,7 +1918,7 @@ namespace __rb_tree pair<const_iterator, const_iterator> equal_range(const key_type& __k) const; -#if __cplusplus >= 201402L +#ifdef __glibcxx_generic_associative_lookup // C++ >= 14 template<typename _Kt, typename _Req = __has_is_transparent_t<_Compare, _Kt>> iterator @@ -2007,7 +2007,7 @@ namespace __rb_tree ++__high; return { __low, __high }; } -#endif +#endif // __glibcxx_generic_associative_lookup // Debugging. bool diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h b/libstdc++-v3/include/bits/stl_uninitialized.h index b1428db..70a5646 100644 --- a/libstdc++-v3/include/bits/stl_uninitialized.h +++ b/libstdc++-v3/include/bits/stl_uninitialized.h @@ -118,7 +118,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ~_UninitDestroyGuard() { if (__builtin_expect(_M_cur != 0, 0)) +#if __cplusplus == 201703L + // std::uninitialized_{value,default}{,_n} can construct array types, + // but std::_Destroy cannot handle them until C++20 (PR 120397). + _S_destroy(_M_first, *_M_cur); +#else std::_Destroy(_M_first, *_M_cur); +#endif } _GLIBCXX20_CONSTEXPR @@ -129,6 +135,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION private: _UninitDestroyGuard(const _UninitDestroyGuard&); + +#if __cplusplus == 201703L + template<typename _Iter> + static void + _S_destroy(_Iter __first, _Iter __last) + { + using _ValT = typename iterator_traits<_Iter>::value_type; + if constexpr (is_array<_ValT>::value) + for (; __first != __last; ++__first) + _S_destroy(*__first, *__first + extent<_ValT>::value); + else + std::_Destroy(__first, __last); + } +#endif }; // This is the default implementation of std::uninitialized_copy. @@ -216,6 +236,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wc++17-extensions" +#pragma GCC diagnostic ignored "-Wclass-memaccess" /** * @brief Copies the range [first,last) into result. * @param __first An input iterator. @@ -357,7 +378,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::__niter_base(__last), __x); else - std::__do_uninit_copy(__first, __last, __x); + std::__do_uninit_fill(__first, __last, __x); } // Overload for pointers. @@ -407,6 +428,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 201103L #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wc++17-extensions" +#pragma GCC diagnostic ignored "-Wclass-memaccess" #if __glibcxx_raw_memory_algorithms >= 202411L // >= C++26 if consteval { return std::__do_uninit_fill(__first, __last, __x); @@ -509,6 +531,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wc++17-extensions" +#pragma GCC diagnostic ignored "-Wclass-memaccess" // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 1339. uninitialized_fill_n should return the end of its range /** @@ -839,7 +862,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { _UninitDestroyGuard<_ForwardIterator> __guard(__first); for (; __first != __last; ++__first) - std::_Construct(std::__addressof(*__first)); + std::_Construct(std::addressof(*__first)); __guard.release(); } }; @@ -856,7 +879,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return; typename iterator_traits<_ForwardIterator>::value_type* __val - = std::__addressof(*__first); + = std::addressof(*__first); std::_Construct(__val); if (++__first != __last) std::fill(__first, __last, *__val); @@ -873,7 +896,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { _UninitDestroyGuard<_ForwardIterator> __guard(__first); for (; __n > 0; --__n, (void) ++__first) - std::_Construct(std::__addressof(*__first)); + std::_Construct(std::addressof(*__first)); __guard.release(); return __first; } @@ -890,7 +913,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__n > 0) { typename iterator_traits<_ForwardIterator>::value_type* __val - = std::__addressof(*__first); + = std::addressof(*__first); std::_Construct(__val); ++__first; __first = std::fill_n(__first, __n - 1, *__val); @@ -902,11 +925,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // __uninitialized_default // Fills [first, last) with value-initialized value_types. template<typename _ForwardIterator> - _GLIBCXX26_CONSTEXPR + _GLIBCXX20_CONSTEXPR inline void __uninitialized_default(_ForwardIterator __first, _ForwardIterator __last) { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __uninitialized_default_1<false>:: + __uninit_default(__first, __last); +#endif + typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType; // trivial types can have deleted assignment @@ -955,7 +984,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __alloc); typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; for (; __first != __last; ++__first) - __traits::construct(__alloc, std::__addressof(*__first)); + __traits::construct(__alloc, std::addressof(*__first)); __guard.release(); } @@ -980,7 +1009,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __alloc); typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; for (; __n > 0; --__n, (void) ++__first) - __traits::construct(__alloc, std::__addressof(*__first)); + __traits::construct(__alloc, std::addressof(*__first)); __guard.release(); return __first; } @@ -1007,7 +1036,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { _UninitDestroyGuard<_ForwardIterator> __guard(__first); for (; __first != __last; ++__first) - std::_Construct_novalue(std::__addressof(*__first)); + std::_Construct_novalue(std::addressof(*__first)); __guard.release(); } }; @@ -1033,7 +1062,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { _UninitDestroyGuard<_ForwardIterator> __guard(__first); for (; __n > 0; --__n, (void) ++__first) - std::_Construct_novalue(std::__addressof(*__first)); + std::_Construct_novalue(std::addressof(*__first)); __guard.release(); return __first; } @@ -1089,7 +1118,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { _UninitDestroyGuard<_ForwardIterator> __guard(__result); for (; __n > 0; --__n, (void) ++__first, ++__result) - std::_Construct(std::__addressof(*__result), *__first); + std::_Construct(std::addressof(*__result), *__first); __guard.release(); return __result; } @@ -1112,7 +1141,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { _UninitDestroyGuard<_ForwardIterator> __guard(__result); for (; __n > 0; --__n, (void) ++__first, ++__result) - std::_Construct(std::__addressof(*__result), *__first); + std::_Construct(std::addressof(*__result), *__first); __guard.release(); return {__first, __result}; } @@ -1239,9 +1268,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION uninitialized_move(_InputIterator __first, _InputIterator __last, _ForwardIterator __result) { - return std::uninitialized_copy - (_GLIBCXX_MAKE_MOVE_ITERATOR(__first), - _GLIBCXX_MAKE_MOVE_ITERATOR(__last), __result); + return std::uninitialized_copy(std::make_move_iterator(__first), + std::make_move_iterator(__last), + __result); } /** @@ -1258,9 +1287,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION uninitialized_move_n(_InputIterator __first, _Size __count, _ForwardIterator __result) { - auto __res = std::__uninitialized_copy_n_pair - (_GLIBCXX_MAKE_MOVE_ITERATOR(__first), - __count, __result); + auto __res + = std::__uninitialized_copy_n_pair(std::make_move_iterator(__first), + __count, __result); return {__res.first.base(), __res.second}; } #endif // __glibcxx_raw_memory_algorithms @@ -1276,11 +1305,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION noexcept(noexcept(std::allocator_traits<_Allocator>::construct(__alloc, __dest, std::move(*__orig))) && noexcept(std::allocator_traits<_Allocator>::destroy( - __alloc, std::__addressof(*__orig)))) + __alloc, std::addressof(*__orig)))) { typedef std::allocator_traits<_Allocator> __traits; __traits::construct(__alloc, __dest, std::move(*__orig)); - __traits::destroy(__alloc, std::__addressof(*__orig)); + __traits::destroy(__alloc, std::addressof(*__orig)); } // This class may be specialized for specific types. @@ -1308,8 +1337,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION "relocation is only possible for values of the same type"); _ForwardIterator __cur = __result; for (; __first != __last; ++__first, (void)++__cur) - std::__relocate_object_a(std::__addressof(*__cur), - std::__addressof(*__first), __alloc); + std::__relocate_object_a(std::addressof(*__cur), + std::addressof(*__first), __alloc); return __cur; } diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index 57680b7..7625333 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -372,8 +372,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX20_CONSTEXPR ~_Vector_base() _GLIBCXX_NOEXCEPT { - _M_deallocate(_M_impl._M_start, - _M_impl._M_end_of_storage - _M_impl._M_start); + ptrdiff_t __n = _M_impl._M_end_of_storage - _M_impl._M_start; + if (__n < 0) + __builtin_unreachable(); + _M_deallocate(_M_impl._M_start, size_t(__n)); } public: @@ -1106,7 +1108,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { ptrdiff_t __dif = this->_M_impl._M_finish - this->_M_impl._M_start; if (__dif < 0) - __builtin_unreachable (); + __builtin_unreachable(); return size_type(__dif); } @@ -1152,7 +1154,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER resize(size_type __new_size, const value_type& __x) { if (__new_size > size()) - _M_fill_insert(end(), __new_size - size(), __x); + _M_fill_append(__new_size - size(), __x); else if (__new_size < size()) _M_erase_at_end(this->_M_impl._M_start + __new_size); } @@ -1173,7 +1175,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER resize(size_type __new_size, value_type __x = value_type()) { if (__new_size > size()) - _M_fill_insert(end(), __new_size - size(), __x); + _M_fill_append(__new_size - size(), __x); else if (__new_size < size()) _M_erase_at_end(this->_M_impl._M_start + __new_size); } @@ -1198,7 +1200,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER ptrdiff_t __dif = this->_M_impl._M_end_of_storage - this->_M_impl._M_start; if (__dif < 0) - __builtin_unreachable (); + __builtin_unreachable(); return size_type(__dif); } @@ -1969,8 +1971,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_range_initialize_n(_Iterator __first, _Sentinel __last, size_type __n) { - pointer __start = this->_M_impl._M_start = + pointer __start = this->_M_allocate(_S_check_init_len(__n, _M_get_Tp_allocator())); + this->_M_impl._M_start = this->_M_impl._M_finish = __start; this->_M_impl._M_end_of_storage = __start + __n; this->_M_impl._M_finish = std::__uninitialized_copy_a(_GLIBCXX_MOVE(__first), __last, @@ -2085,6 +2088,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void _M_fill_insert(iterator __pos, size_type __n, const value_type& __x); + // Called by resize(n,x), and the _M_fill_insert(end(), n, x) + _GLIBCXX20_CONSTEXPR + void + _M_fill_append(size_type __n, const value_type& __x); + #if __cplusplus >= 201103L // Called by resize(n). _GLIBCXX20_CONSTEXPR diff --git a/libstdc++-v3/include/bits/this_thread_sleep.h b/libstdc++-v3/include/bits/this_thread_sleep.h index 57f89f8..7c9d573 100644 --- a/libstdc++-v3/include/bits/this_thread_sleep.h +++ b/libstdc++-v3/include/bits/this_thread_sleep.h @@ -59,11 +59,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { #ifndef _GLIBCXX_NO_SLEEP -#ifndef _GLIBCXX_USE_NANOSLEEP - void - __sleep_for(chrono::seconds, chrono::nanoseconds); -#endif - /// this_thread::sleep_for template<typename _Rep, typename _Period> inline void @@ -71,18 +66,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { if (__rtime <= __rtime.zero()) return; - auto __s = chrono::duration_cast<chrono::seconds>(__rtime); - auto __ns = chrono::duration_cast<chrono::nanoseconds>(__rtime - __s); + + struct timespec __ts = chrono::__to_timeout_timespec(__rtime); #ifdef _GLIBCXX_USE_NANOSLEEP - struct ::timespec __ts = - { - static_cast<std::time_t>(__s.count()), - static_cast<long>(__ns.count()) - }; while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR) { } #else - __sleep_for(__s, __ns); + using chrono::seconds; + using chrono::nanoseconds; + void __sleep_for(seconds __s, nanoseconds __ns); + __sleep_for(seconds(__ts.tv_sec), nanoseconds(__ts.tv_nsec)); #endif } diff --git a/libstdc++-v3/include/bits/unicode-data.h b/libstdc++-v3/include/bits/unicode-data.h index 0ab5ecb..45a68de 100644 --- a/libstdc++-v3/include/bits/unicode-data.h +++ b/libstdc++-v3/include/bits/unicode-data.h @@ -51,17 +51,17 @@ 0x3250, 0xa48d, 0xa490, 0xa4c7, 0xa960, 0xa97d, 0xac00, 0xd7a4, 0xf900, 0xfb00, 0xfe10, 0xfe1a, 0xfe30, 0xfe53, 0xfe54, 0xfe67, 0xfe68, 0xfe6c, 0xff01, 0xff61, 0xffe0, 0xffe7, 0x16fe0, 0x16fe5, - 0x16ff0, 0x16ff2, 0x17000, 0x187f8, 0x18800, 0x18cd6, 0x18cff, 0x18d09, + 0x16ff0, 0x16ff7, 0x17000, 0x18cd6, 0x18cff, 0x18d1f, 0x18d80, 0x18df3, 0x1aff0, 0x1aff4, 0x1aff5, 0x1affc, 0x1affd, 0x1afff, 0x1b000, 0x1b123, 0x1b132, 0x1b133, 0x1b150, 0x1b153, 0x1b155, 0x1b156, 0x1b164, 0x1b168, 0x1b170, 0x1b2fc, 0x1d300, 0x1d357, 0x1d360, 0x1d377, 0x1f004, 0x1f005, 0x1f0cf, 0x1f0d0, 0x1f18e, 0x1f18f, 0x1f191, 0x1f19b, 0x1f200, 0x1f203, 0x1f210, 0x1f23c, 0x1f240, 0x1f249, 0x1f250, 0x1f252, 0x1f260, 0x1f266, 0x1f300, 0x1f650, 0x1f680, 0x1f6c6, 0x1f6cc, 0x1f6cd, 0x1f6d0, 0x1f6d3, - 0x1f6d5, 0x1f6d8, 0x1f6dc, 0x1f6e0, 0x1f6eb, 0x1f6ed, 0x1f6f4, 0x1f6fd, + 0x1f6d5, 0x1f6d9, 0x1f6dc, 0x1f6e0, 0x1f6eb, 0x1f6ed, 0x1f6f4, 0x1f6fd, 0x1f7e0, 0x1f7ec, 0x1f7f0, 0x1f7f1, 0x1f900, 0x1fa00, 0x1fa70, 0x1fa7d, - 0x1fa80, 0x1fa8a, 0x1fa8f, 0x1fac7, 0x1face, 0x1fadd, 0x1fadf, 0x1faea, - 0x1faf0, 0x1faf9, 0x20000, 0x2fffe, 0x30000, 0x3fffe, + 0x1fa80, 0x1fa8b, 0x1fa8e, 0x1fac7, 0x1fac8, 0x1fac9, 0x1facd, 0x1fadd, + 0x1fadf, 0x1faeb, 0x1faef, 0x1faf9, 0x20000, 0x2fffe, 0x30000, 0x3fffe, }; // Values generated by contrib/unicode/gen_libstdcxx_unicode_data.py, @@ -76,7 +76,7 @@ 0xc39, 0xc3a, 0xdbb, 0xdbc, 0xe1d, 0xe20, 0xe97, 0xe9a, 0xf65, 0xf80, 0xff7, 0xffa, 0x105d, 0x1060, 0x107f, 0x1080, 0x10b9, 0x10bc, - 0x10bf, 0x10c0, 0x10d7, 0x10e0, 0x111f, 0x112e, + 0x10bf, 0x10c0, 0x10d7, 0x10e0, 0x1121, 0x112e, 0x11c5, 0x11c6, 0x1309, 0x130a, 0x131b, 0x131e, 0x1323, 0x1326, 0x1353, 0x1354, 0x1363, 0x1364, 0x1367, 0x136c, 0x1375, 0x1378, 0x138b, 0x138e, @@ -104,11 +104,11 @@ 0x17a3, 0x17ae, 0x17b1, 0x17cc, 0x17f7, 0x1800, 0x181b, 0x181c, 0x1823, 0x1824, 0x1853, 0x1854, 0x1875, 0x1878, 0x188b, 0x188c, 0x1893, 0x1894, - 0x189d, 0x18aa, 0x18af, 0x18b0, 0x18b7, 0x18ba, + 0x189d, 0x18aa, 0x18af, 0x18b0, 0x18b7, 0x18b8, 0x18bd, 0x18c0, 0x18c9, 0x18cc, 0x18e1, 0x18ee, 0x191b, 0x191c, 0x1923, 0x1924, 0x1953, 0x1954, 0x1969, 0x196a, 0x1975, 0x1978, 0x198b, 0x198c, - 0x1993, 0x1994, 0x199d, 0x19aa, 0x19af, 0x19ba, + 0x1993, 0x1994, 0x199d, 0x19aa, 0x19af, 0x19b8, 0x19bf, 0x19c0, 0x19c9, 0x19cc, 0x19e1, 0x19e2, 0x19e9, 0x1a00, 0x1a1b, 0x1a1c, 0x1a23, 0x1a24, 0x1a8b, 0x1a8c, 0x1a93, 0x1a94, 0x1aa1, 0x1aa8, @@ -141,19 +141,19 @@ 0x32eb, 0x3300, 0x3359, 0x3360, 0x3395, 0x33a0, 0x33b7, 0x33bc, 0x3439, 0x343c, 0x34bf, 0x34c0, 0x34fb, 0x34fe, 0x3515, 0x3520, 0x3535, 0x3540, - 0x355d, 0x3560, 0x359f, 0x3600, 0x369b, 0x369c, - 0x37e9, 0x37f8, 0x3871, 0x3876, 0x3895, 0x389a, - 0x3917, 0x3920, 0x3977, 0x397a, 0x3991, 0x39a0, - 0x39f7, 0x3a00, 0x3e2d, 0x3e30, 0x3e3d, 0x3e40, - 0x3e8d, 0x3e90, 0x3e9d, 0x3ea0, 0x3eb1, 0x3eb2, - 0x3eb5, 0x3eb6, 0x3eb9, 0x3eba, 0x3ebd, 0x3ebe, - 0x3efd, 0x3f00, 0x3f6b, 0x3f6c, 0x3f8b, 0x3f8c, - 0x3fa9, 0x3fac, 0x3fb9, 0x3fba, 0x3fe1, 0x3fe4, - 0x3feb, 0x3fec, 0x3fff, 0x4020, 0x4051, 0x4060, - 0x40bf, 0x40e0, 0x40e5, 0x40e8, 0x411f, 0x4120, - 0x413b, 0x4140, 0x4183, 0x41a0, 0x41e3, 0x4200, - 0x4319, 0x4320, 0x4855, 0x4880, 0x4897, 0x48c0, - 0x56e9, 0x56ec, 0x572d, 0x572e, 0x59e9, 0x59f2, + 0x355d, 0x3560, 0x35bd, 0x35c0, 0x35d9, 0x3600, + 0x369b, 0x369c, 0x37e9, 0x37f8, 0x3871, 0x3876, + 0x3895, 0x389a, 0x3917, 0x3920, 0x3977, 0x397a, + 0x3991, 0x39a0, 0x39f7, 0x3a00, 0x3e2d, 0x3e30, + 0x3e3d, 0x3e40, 0x3e8d, 0x3e90, 0x3e9d, 0x3ea0, + 0x3eb1, 0x3eb2, 0x3eb5, 0x3eb6, 0x3eb9, 0x3eba, + 0x3ebd, 0x3ebe, 0x3efd, 0x3f00, 0x3f6b, 0x3f6c, + 0x3f8b, 0x3f8c, 0x3fa9, 0x3fac, 0x3fb9, 0x3fba, + 0x3fe1, 0x3fe4, 0x3feb, 0x3fec, 0x3fff, 0x4020, + 0x4051, 0x4060, 0x40bf, 0x40e0, 0x40e5, 0x40e8, + 0x411f, 0x4120, 0x413b, 0x4140, 0x4185, 0x41a0, + 0x41e3, 0x4200, 0x4319, 0x4320, 0x4855, 0x4880, + 0x4897, 0x48c0, 0x56e9, 0x56ec, 0x59e9, 0x59f2, 0x5a4d, 0x5a4e, 0x5a51, 0x5a5a, 0x5a5d, 0x5a60, 0x5ad1, 0x5ade, 0x5ae3, 0x5afe, 0x5b2f, 0x5b40, 0x5b4f, 0x5b50, 0x5b5f, 0x5b60, 0x5b6f, 0x5b70, @@ -164,8 +164,7 @@ 0x6201, 0x620a, 0x6261, 0x6262, 0x631f, 0x6320, 0x63cd, 0x63de, 0x643f, 0x6440, 0x1491b, 0x14920, 0x1498f, 0x149a0, 0x14c59, 0x14c80, 0x14df1, 0x14e00, - 0x14f9d, 0x14fa0, 0x14fa5, 0x14fa6, 0x14fa9, 0x14faa, - 0x14fbb, 0x14fe4, 0x1505b, 0x15060, 0x15075, 0x15080, + 0x14fbb, 0x14fe2, 0x1505b, 0x15060, 0x15075, 0x15080, 0x150f1, 0x15100, 0x1518d, 0x1519c, 0x151b5, 0x151c0, 0x152a9, 0x152be, 0x152fb, 0x15300, 0x1539d, 0x1539e, 0x153b5, 0x153bc, 0x153ff, 0x15400, 0x1546f, 0x15480, @@ -177,7 +176,6 @@ 0x1f4dd, 0x1f4e0, 0x1f5b5, 0x1f600, 0x1f60f, 0x1f626, 0x1f631, 0x1f63a, 0x1f66f, 0x1f670, 0x1f67b, 0x1f67c, 0x1f67f, 0x1f680, 0x1f685, 0x1f686, 0x1f68b, 0x1f68c, - 0x1f787, 0x1f7a6, 0x1fb21, 0x1fb24, 0x1fb91, 0x1fb9e, 0x1fba1, 0x1fbe0, 0x1fc35, 0x1fc40, 0x1fca7, 0x1fca8, 0x1fccf, 0x1fcd0, 0x1fcd9, 0x1fce0, 0x1fceb, 0x1fcec, 0x1fdfb, 0x1fe02, 0x1ff7f, 0x1ff84, 0x1ff91, 0x1ff94, @@ -201,7 +199,7 @@ 0x2106d, 0x2106e, 0x21073, 0x21078, 0x2107b, 0x2107e, 0x210ad, 0x210ae, 0x2113f, 0x2114e, 0x21161, 0x211c0, 0x211e7, 0x211e8, 0x211ed, 0x211f6, 0x21239, 0x2123e, - 0x21275, 0x2127e, 0x21281, 0x21300, 0x21371, 0x21378, + 0x21275, 0x2127e, 0x212b5, 0x21300, 0x21371, 0x21378, 0x213a1, 0x213a4, 0x21409, 0x2140a, 0x2140f, 0x21418, 0x21429, 0x2142a, 0x21431, 0x21432, 0x2146d, 0x21470, 0x21477, 0x2147e, 0x21493, 0x214a0, 0x214b3, 0x214c0, @@ -212,108 +210,112 @@ 0x21a51, 0x21a60, 0x21a75, 0x21a80, 0x21acd, 0x21ad2, 0x21b0d, 0x21b1c, 0x21b21, 0x21cc0, 0x21cff, 0x21d00, 0x21d55, 0x21d56, 0x21d5d, 0x21d60, 0x21d65, 0x21d84, - 0x21d8b, 0x21df8, 0x21e51, 0x21e60, 0x21eb5, 0x21ee0, - 0x21f15, 0x21f60, 0x21f99, 0x21fc0, 0x21fef, 0x22000, - 0x2209d, 0x220a4, 0x220ed, 0x220fe, 0x2217b, 0x2217c, - 0x22187, 0x221a0, 0x221d3, 0x221e0, 0x221f5, 0x22200, - 0x2226b, 0x2226c, 0x22291, 0x222a0, 0x222ef, 0x22300, - 0x223c1, 0x223c2, 0x223eb, 0x22400, 0x22425, 0x22426, - 0x22485, 0x22500, 0x2250f, 0x22510, 0x22513, 0x22514, - 0x2251d, 0x2251e, 0x2253d, 0x2253e, 0x22555, 0x22560, - 0x225d7, 0x225e0, 0x225f5, 0x22600, 0x22609, 0x2260a, - 0x2261b, 0x2261e, 0x22623, 0x22626, 0x22653, 0x22654, - 0x22663, 0x22664, 0x22669, 0x2266a, 0x22675, 0x22676, - 0x2268b, 0x2268e, 0x22693, 0x22696, 0x2269d, 0x226a0, - 0x226a3, 0x226ae, 0x226b1, 0x226ba, 0x226c9, 0x226cc, - 0x226db, 0x226e0, 0x226eb, 0x22700, 0x22715, 0x22716, - 0x22719, 0x2271c, 0x2271f, 0x22720, 0x2276d, 0x2276e, - 0x22783, 0x22784, 0x22787, 0x2278a, 0x2278d, 0x2278e, - 0x22797, 0x22798, 0x227ad, 0x227ae, 0x227b3, 0x227c2, - 0x227c7, 0x22800, 0x228b9, 0x228ba, 0x228c5, 0x22900, - 0x22991, 0x229a0, 0x229b5, 0x22b00, 0x22b6d, 0x22b70, - 0x22bbd, 0x22c00, 0x22c8b, 0x22ca0, 0x22cb5, 0x22cc0, - 0x22cdb, 0x22d00, 0x22d75, 0x22d80, 0x22d95, 0x22da0, - 0x22dc9, 0x22e00, 0x22e37, 0x22e3a, 0x22e59, 0x22e60, - 0x22e8f, 0x23000, 0x23079, 0x23140, 0x231e7, 0x231fe, - 0x2320f, 0x23212, 0x23215, 0x23218, 0x23229, 0x2322a, - 0x2322f, 0x23230, 0x2326d, 0x2326e, 0x23273, 0x23276, - 0x2328f, 0x232a0, 0x232b5, 0x23340, 0x23351, 0x23354, - 0x233b1, 0x233b4, 0x233cb, 0x23400, 0x23491, 0x234a0, - 0x23547, 0x23560, 0x235f3, 0x23600, 0x23615, 0x23780, - 0x237c5, 0x237e0, 0x237f5, 0x23800, 0x23813, 0x23814, - 0x2386f, 0x23870, 0x2388d, 0x238a0, 0x238db, 0x238e0, - 0x23921, 0x23924, 0x23951, 0x23952, 0x2396f, 0x23a00, - 0x23a0f, 0x23a10, 0x23a15, 0x23a16, 0x23a6f, 0x23a74, - 0x23a77, 0x23a78, 0x23a7d, 0x23a7e, 0x23a91, 0x23aa0, - 0x23ab5, 0x23ac0, 0x23acd, 0x23ace, 0x23ad3, 0x23ad4, - 0x23b1f, 0x23b20, 0x23b25, 0x23b26, 0x23b33, 0x23b40, - 0x23b55, 0x23dc0, 0x23df3, 0x23e00, 0x23e23, 0x23e24, - 0x23e77, 0x23e7c, 0x23eb7, 0x23f60, 0x23f63, 0x23f80, - 0x23fe5, 0x23ffe, 0x24735, 0x24800, 0x248df, 0x248e0, - 0x248eb, 0x24900, 0x24a89, 0x25f20, 0x25fe7, 0x26000, - 0x26861, 0x26880, 0x268ad, 0x268c0, 0x287f7, 0x28800, - 0x28c8f, 0x2c200, 0x2c275, 0x2d000, 0x2d473, 0x2d480, - 0x2d4bf, 0x2d4c0, 0x2d4d5, 0x2d4dc, 0x2d57f, 0x2d580, - 0x2d595, 0x2d5a0, 0x2d5dd, 0x2d5e0, 0x2d5ed, 0x2d600, - 0x2d68d, 0x2d6a0, 0x2d6b5, 0x2d6b6, 0x2d6c5, 0x2d6c6, - 0x2d6f1, 0x2d6fa, 0x2d721, 0x2da80, 0x2daf5, 0x2dc80, - 0x2dd37, 0x2de00, 0x2de97, 0x2de9e, 0x2df11, 0x2df1e, - 0x2df41, 0x2dfc0, 0x2dfcb, 0x2dfe0, 0x2dfe5, 0x2e000, - 0x30ff1, 0x31000, 0x319ad, 0x319fe, 0x31a13, 0x35fe0, + 0x21d91, 0x21da0, 0x21db3, 0x21df4, 0x21e51, 0x21e60, + 0x21eb5, 0x21ee0, 0x21f15, 0x21f60, 0x21f99, 0x21fc0, + 0x21fef, 0x22000, 0x2209d, 0x220a4, 0x220ed, 0x220fe, + 0x2217b, 0x2217c, 0x22187, 0x221a0, 0x221d3, 0x221e0, + 0x221f5, 0x22200, 0x2226b, 0x2226c, 0x22291, 0x222a0, + 0x222ef, 0x22300, 0x223c1, 0x223c2, 0x223eb, 0x22400, + 0x22425, 0x22426, 0x22485, 0x22500, 0x2250f, 0x22510, + 0x22513, 0x22514, 0x2251d, 0x2251e, 0x2253d, 0x2253e, + 0x22555, 0x22560, 0x225d7, 0x225e0, 0x225f5, 0x22600, + 0x22609, 0x2260a, 0x2261b, 0x2261e, 0x22623, 0x22626, + 0x22653, 0x22654, 0x22663, 0x22664, 0x22669, 0x2266a, + 0x22675, 0x22676, 0x2268b, 0x2268e, 0x22693, 0x22696, + 0x2269d, 0x226a0, 0x226a3, 0x226ae, 0x226b1, 0x226ba, + 0x226c9, 0x226cc, 0x226db, 0x226e0, 0x226eb, 0x22700, + 0x22715, 0x22716, 0x22719, 0x2271c, 0x2271f, 0x22720, + 0x2276d, 0x2276e, 0x22783, 0x22784, 0x22787, 0x2278a, + 0x2278d, 0x2278e, 0x22797, 0x22798, 0x227ad, 0x227ae, + 0x227b3, 0x227c2, 0x227c7, 0x22800, 0x228b9, 0x228ba, + 0x228c5, 0x22900, 0x22991, 0x229a0, 0x229b5, 0x22b00, + 0x22b6d, 0x22b70, 0x22bbd, 0x22c00, 0x22c8b, 0x22ca0, + 0x22cb5, 0x22cc0, 0x22cdb, 0x22d00, 0x22d75, 0x22d80, + 0x22d95, 0x22da0, 0x22dc9, 0x22e00, 0x22e37, 0x22e3a, + 0x22e59, 0x22e60, 0x22e8f, 0x23000, 0x23079, 0x23140, + 0x231e7, 0x231fe, 0x2320f, 0x23212, 0x23215, 0x23218, + 0x23229, 0x2322a, 0x2322f, 0x23230, 0x2326d, 0x2326e, + 0x23273, 0x23276, 0x2328f, 0x232a0, 0x232b5, 0x23340, + 0x23351, 0x23354, 0x233b1, 0x233b4, 0x233cb, 0x23400, + 0x23491, 0x234a0, 0x23547, 0x23560, 0x235f3, 0x23600, + 0x23615, 0x236c0, 0x236d1, 0x23780, 0x237c5, 0x237e0, + 0x237f5, 0x23800, 0x23813, 0x23814, 0x2386f, 0x23870, + 0x2388d, 0x238a0, 0x238db, 0x238e0, 0x23921, 0x23924, + 0x23951, 0x23952, 0x2396f, 0x23a00, 0x23a0f, 0x23a10, + 0x23a15, 0x23a16, 0x23a6f, 0x23a74, 0x23a77, 0x23a78, + 0x23a7d, 0x23a7e, 0x23a91, 0x23aa0, 0x23ab5, 0x23ac0, + 0x23acd, 0x23ace, 0x23ad3, 0x23ad4, 0x23b1f, 0x23b20, + 0x23b25, 0x23b26, 0x23b33, 0x23b40, 0x23b55, 0x23b60, + 0x23bb9, 0x23bc0, 0x23bd5, 0x23dc0, 0x23df3, 0x23e00, + 0x23e23, 0x23e24, 0x23e77, 0x23e7c, 0x23eb7, 0x23f60, + 0x23f63, 0x23f80, 0x23fe5, 0x23ffe, 0x24735, 0x24800, + 0x248df, 0x248e0, 0x248eb, 0x24900, 0x24a89, 0x25f20, + 0x25fe7, 0x26000, 0x26861, 0x26880, 0x268ad, 0x268c0, + 0x287f7, 0x28800, 0x28c8f, 0x2c200, 0x2c275, 0x2d000, + 0x2d473, 0x2d480, 0x2d4bf, 0x2d4c0, 0x2d4d5, 0x2d4dc, + 0x2d57f, 0x2d580, 0x2d595, 0x2d5a0, 0x2d5dd, 0x2d5e0, + 0x2d5ed, 0x2d600, 0x2d68d, 0x2d6a0, 0x2d6b5, 0x2d6b6, + 0x2d6c5, 0x2d6c6, 0x2d6f1, 0x2d6fa, 0x2d721, 0x2da80, + 0x2daf5, 0x2dc80, 0x2dd37, 0x2dd40, 0x2dd73, 0x2dd76, + 0x2dda9, 0x2de00, 0x2de97, 0x2de9e, 0x2df11, 0x2df1e, + 0x2df41, 0x2dfc0, 0x2dfcb, 0x2dfe0, 0x2dfef, 0x2e000, + 0x319ad, 0x319fe, 0x31a3f, 0x31b00, 0x31be7, 0x35fe0, 0x35fe9, 0x35fea, 0x35ff9, 0x35ffa, 0x35fff, 0x36000, 0x36247, 0x36264, 0x36267, 0x362a0, 0x362a7, 0x362aa, 0x362ad, 0x362c8, 0x362d1, 0x362e0, 0x365f9, 0x37800, 0x378d7, 0x378e0, 0x378fb, 0x37900, 0x37913, 0x37920, - 0x37935, 0x37938, 0x37941, 0x39800, 0x399f5, 0x39a00, - 0x39d69, 0x39e00, 0x39e5d, 0x39e60, 0x39e8f, 0x39ea0, - 0x39f89, 0x3a000, 0x3a1ed, 0x3a200, 0x3a24f, 0x3a252, - 0x3a2e7, 0x3a2f6, 0x3a3d7, 0x3a400, 0x3a48d, 0x3a580, - 0x3a5a9, 0x3a5c0, 0x3a5e9, 0x3a600, 0x3a6af, 0x3a6c0, - 0x3a6f3, 0x3a800, 0x3a8ab, 0x3a8ac, 0x3a93b, 0x3a93c, - 0x3a941, 0x3a944, 0x3a947, 0x3a94a, 0x3a94f, 0x3a952, - 0x3a95b, 0x3a95c, 0x3a975, 0x3a976, 0x3a979, 0x3a97a, - 0x3a989, 0x3a98a, 0x3aa0d, 0x3aa0e, 0x3aa17, 0x3aa1a, - 0x3aa2b, 0x3aa2c, 0x3aa3b, 0x3aa3c, 0x3aa75, 0x3aa76, - 0x3aa7f, 0x3aa80, 0x3aa8b, 0x3aa8c, 0x3aa8f, 0x3aa94, - 0x3aaa3, 0x3aaa4, 0x3ad4d, 0x3ad50, 0x3af99, 0x3af9c, - 0x3b519, 0x3b536, 0x3b541, 0x3b542, 0x3b561, 0x3be00, - 0x3be3f, 0x3be4a, 0x3be57, 0x3c000, 0x3c00f, 0x3c010, - 0x3c033, 0x3c036, 0x3c045, 0x3c046, 0x3c04b, 0x3c04c, - 0x3c057, 0x3c060, 0x3c0dd, 0x3c11e, 0x3c121, 0x3c200, - 0x3c25b, 0x3c260, 0x3c27d, 0x3c280, 0x3c295, 0x3c29c, - 0x3c2a1, 0x3c520, 0x3c55f, 0x3c580, 0x3c5f5, 0x3c5fe, - 0x3c601, 0x3c9a0, 0x3c9f5, 0x3cba0, 0x3cbf7, 0x3cbfe, - 0x3cc01, 0x3cfc0, 0x3cfcf, 0x3cfd0, 0x3cfd9, 0x3cfda, - 0x3cfdf, 0x3cfe0, 0x3cfff, 0x3d000, 0x3d18b, 0x3d18e, - 0x3d1af, 0x3d200, 0x3d299, 0x3d2a0, 0x3d2b5, 0x3d2bc, - 0x3d2c1, 0x3d8e2, 0x3d96b, 0x3da02, 0x3da7d, 0x3dc00, - 0x3dc09, 0x3dc0a, 0x3dc41, 0x3dc42, 0x3dc47, 0x3dc48, - 0x3dc4b, 0x3dc4e, 0x3dc51, 0x3dc52, 0x3dc67, 0x3dc68, - 0x3dc71, 0x3dc72, 0x3dc75, 0x3dc76, 0x3dc79, 0x3dc84, - 0x3dc87, 0x3dc8e, 0x3dc91, 0x3dc92, 0x3dc95, 0x3dc96, - 0x3dc99, 0x3dc9a, 0x3dca1, 0x3dca2, 0x3dca7, 0x3dca8, - 0x3dcab, 0x3dcae, 0x3dcb1, 0x3dcb2, 0x3dcb5, 0x3dcb6, - 0x3dcb9, 0x3dcba, 0x3dcbd, 0x3dcbe, 0x3dcc1, 0x3dcc2, - 0x3dcc7, 0x3dcc8, 0x3dccb, 0x3dcce, 0x3dcd7, 0x3dcd8, - 0x3dce7, 0x3dce8, 0x3dcf1, 0x3dcf2, 0x3dcfb, 0x3dcfc, - 0x3dcff, 0x3dd00, 0x3dd15, 0x3dd16, 0x3dd39, 0x3dd42, - 0x3dd49, 0x3dd4a, 0x3dd55, 0x3dd56, 0x3dd79, 0x3dde0, - 0x3dde5, 0x3e000, 0x3e059, 0x3e060, 0x3e129, 0x3e140, - 0x3e15f, 0x3e162, 0x3e181, 0x3e182, 0x3e1a1, 0x3e1a2, - 0x3e1ed, 0x3e200, 0x3e35d, 0x3e3cc, 0x3e407, 0x3e420, - 0x3e479, 0x3e480, 0x3e493, 0x3e4a0, 0x3e4a5, 0x3e4c0, - 0x3e4cd, 0x3e600, 0x3edb1, 0x3edb8, 0x3eddb, 0x3ede0, - 0x3edfb, 0x3ee00, 0x3eeef, 0x3eef6, 0x3efb5, 0x3efc0, - 0x3efd9, 0x3efe0, 0x3efe3, 0x3f000, 0x3f019, 0x3f020, - 0x3f091, 0x3f0a0, 0x3f0b5, 0x3f0c0, 0x3f111, 0x3f120, - 0x3f15d, 0x3f160, 0x3f179, 0x3f180, 0x3f185, 0x3f200, - 0x3f4a9, 0x3f4c0, 0x3f4dd, 0x3f4e0, 0x3f4fb, 0x3f500, - 0x3f515, 0x3f51e, 0x3f58f, 0x3f59c, 0x3f5bb, 0x3f5be, - 0x3f5d5, 0x3f5e0, 0x3f5f3, 0x3f600, 0x3f727, 0x3f728, - 0x3f7f5, 0x40000, 0x54dc1, 0x54e00, 0x56e75, 0x56e80, - 0x5703d, 0x57040, 0x59d45, 0x59d60, 0x5d7c3, 0x5d7e0, - 0x5dcbd, 0x5f000, 0x5f43d, 0x60000, 0x62697, 0x626a0, - 0x64761, 0x1c0200, 0x1c03e1, + 0x37935, 0x37938, 0x37941, 0x39800, 0x399fb, 0x39a00, + 0x39d69, 0x39d74, 0x39da3, 0x39dc0, 0x39de3, 0x39e00, + 0x39e5d, 0x39e60, 0x39e8f, 0x39ea0, 0x39f89, 0x3a000, + 0x3a1ed, 0x3a200, 0x3a24f, 0x3a252, 0x3a2e7, 0x3a2f6, + 0x3a3d7, 0x3a400, 0x3a48d, 0x3a580, 0x3a5a9, 0x3a5c0, + 0x3a5e9, 0x3a600, 0x3a6af, 0x3a6c0, 0x3a6f3, 0x3a800, + 0x3a8ab, 0x3a8ac, 0x3a93b, 0x3a93c, 0x3a941, 0x3a944, + 0x3a947, 0x3a94a, 0x3a94f, 0x3a952, 0x3a95b, 0x3a95c, + 0x3a975, 0x3a976, 0x3a979, 0x3a97a, 0x3a989, 0x3a98a, + 0x3aa0d, 0x3aa0e, 0x3aa17, 0x3aa1a, 0x3aa2b, 0x3aa2c, + 0x3aa3b, 0x3aa3c, 0x3aa75, 0x3aa76, 0x3aa7f, 0x3aa80, + 0x3aa8b, 0x3aa8c, 0x3aa8f, 0x3aa94, 0x3aaa3, 0x3aaa4, + 0x3ad4d, 0x3ad50, 0x3af99, 0x3af9c, 0x3b519, 0x3b536, + 0x3b541, 0x3b542, 0x3b561, 0x3be00, 0x3be3f, 0x3be4a, + 0x3be57, 0x3c000, 0x3c00f, 0x3c010, 0x3c033, 0x3c036, + 0x3c045, 0x3c046, 0x3c04b, 0x3c04c, 0x3c057, 0x3c060, + 0x3c0dd, 0x3c11e, 0x3c121, 0x3c200, 0x3c25b, 0x3c260, + 0x3c27d, 0x3c280, 0x3c295, 0x3c29c, 0x3c2a1, 0x3c520, + 0x3c55f, 0x3c580, 0x3c5f5, 0x3c5fe, 0x3c601, 0x3c9a0, + 0x3c9f5, 0x3cba0, 0x3cbf7, 0x3cbfe, 0x3cc01, 0x3cd80, + 0x3cdbf, 0x3cdc0, 0x3cded, 0x3cdfc, 0x3ce01, 0x3cfc0, + 0x3cfcf, 0x3cfd0, 0x3cfd9, 0x3cfda, 0x3cfdf, 0x3cfe0, + 0x3cfff, 0x3d000, 0x3d18b, 0x3d18e, 0x3d1af, 0x3d200, + 0x3d299, 0x3d2a0, 0x3d2b5, 0x3d2bc, 0x3d2c1, 0x3d8e2, + 0x3d96b, 0x3da02, 0x3da7d, 0x3dc00, 0x3dc09, 0x3dc0a, + 0x3dc41, 0x3dc42, 0x3dc47, 0x3dc48, 0x3dc4b, 0x3dc4e, + 0x3dc51, 0x3dc52, 0x3dc67, 0x3dc68, 0x3dc71, 0x3dc72, + 0x3dc75, 0x3dc76, 0x3dc79, 0x3dc84, 0x3dc87, 0x3dc8e, + 0x3dc91, 0x3dc92, 0x3dc95, 0x3dc96, 0x3dc99, 0x3dc9a, + 0x3dca1, 0x3dca2, 0x3dca7, 0x3dca8, 0x3dcab, 0x3dcae, + 0x3dcb1, 0x3dcb2, 0x3dcb5, 0x3dcb6, 0x3dcb9, 0x3dcba, + 0x3dcbd, 0x3dcbe, 0x3dcc1, 0x3dcc2, 0x3dcc7, 0x3dcc8, + 0x3dccb, 0x3dcce, 0x3dcd7, 0x3dcd8, 0x3dce7, 0x3dce8, + 0x3dcf1, 0x3dcf2, 0x3dcfb, 0x3dcfc, 0x3dcff, 0x3dd00, + 0x3dd15, 0x3dd16, 0x3dd39, 0x3dd42, 0x3dd49, 0x3dd4a, + 0x3dd55, 0x3dd56, 0x3dd79, 0x3dde0, 0x3dde5, 0x3e000, + 0x3e059, 0x3e060, 0x3e129, 0x3e140, 0x3e15f, 0x3e162, + 0x3e181, 0x3e182, 0x3e1a1, 0x3e1a2, 0x3e1ed, 0x3e200, + 0x3e35d, 0x3e3cc, 0x3e407, 0x3e420, 0x3e479, 0x3e480, + 0x3e493, 0x3e4a0, 0x3e4a5, 0x3e4c0, 0x3e4cd, 0x3e600, + 0x3edb3, 0x3edb8, 0x3eddb, 0x3ede0, 0x3edfb, 0x3ee00, + 0x3efb5, 0x3efc0, 0x3efd9, 0x3efe0, 0x3efe3, 0x3f000, + 0x3f019, 0x3f020, 0x3f091, 0x3f0a0, 0x3f0b5, 0x3f0c0, + 0x3f111, 0x3f120, 0x3f15d, 0x3f160, 0x3f179, 0x3f180, + 0x3f185, 0x3f1a0, 0x3f1b3, 0x3f200, 0x3f4b1, 0x3f4c0, + 0x3f4dd, 0x3f4e0, 0x3f4fb, 0x3f500, 0x3f517, 0x3f51c, + 0x3f58f, 0x3f590, 0x3f593, 0x3f59a, 0x3f5bb, 0x3f5be, + 0x3f5d7, 0x3f5de, 0x3f5f3, 0x3f600, 0x3f727, 0x3f728, + 0x3f7f7, 0x40000, 0x54dc1, 0x54e00, 0x5703d, 0x57040, + 0x59d5d, 0x59d60, 0x5d7c3, 0x5d7e0, 0x5dcbd, 0x5f000, + 0x5f43d, 0x60000, 0x62697, 0x626a0, 0x668f5, 0x1c0200, + 0x1c03e1, }; enum class _Gcb_property { @@ -399,236 +401,238 @@ 0x19336, 0x19394, 0x193c0, 0x1a174, 0x1a196, 0x1a1b4, 0x1a1c0, 0x1a556, 0x1a564, 0x1a576, 0x1a584, 0x1a5f0, 0x1a604, 0x1a610, 0x1a624, 0x1a630, 0x1a654, 0x1a6d6, - 0x1a734, 0x1a7d0, 0x1a7f4, 0x1a800, 0x1ab04, 0x1acf0, - 0x1b004, 0x1b046, 0x1b050, 0x1b344, 0x1b3e6, 0x1b424, - 0x1b450, 0x1b6b4, 0x1b740, 0x1b804, 0x1b826, 0x1b830, - 0x1ba16, 0x1ba24, 0x1ba66, 0x1ba84, 0x1bae0, 0x1be64, - 0x1be76, 0x1be84, 0x1bea6, 0x1bed4, 0x1bee6, 0x1bef4, - 0x1bf40, 0x1c246, 0x1c2c4, 0x1c346, 0x1c364, 0x1c380, - 0x1cd04, 0x1cd30, 0x1cd44, 0x1ce16, 0x1ce24, 0x1ce90, - 0x1ced4, 0x1cee0, 0x1cf44, 0x1cf50, 0x1cf76, 0x1cf84, - 0x1cfa0, 0x1dc04, 0x1e000, 0x200b1, 0x200c4, 0x200da, - 0x200e1, 0x20100, 0x20281, 0x202f0, 0x20601, 0x20700, - 0x20d04, 0x20f10, 0x2cef4, 0x2cf20, 0x2d7f4, 0x2d800, - 0x2de04, 0x2e000, 0x302a4, 0x30300, 0x30994, 0x309b0, - 0xa66f4, 0xa6730, 0xa6744, 0xa67e0, 0xa69e4, 0xa6a00, - 0xa6f04, 0xa6f20, 0xa8024, 0xa8030, 0xa8064, 0xa8070, - 0xa80b4, 0xa80c0, 0xa8236, 0xa8254, 0xa8276, 0xa8280, - 0xa82c4, 0xa82d0, 0xa8806, 0xa8820, 0xa8b46, 0xa8c44, - 0xa8c60, 0xa8e04, 0xa8f20, 0xa8ff4, 0xa9000, 0xa9264, - 0xa92e0, 0xa9474, 0xa9526, 0xa9534, 0xa9540, 0xa9607, - 0xa97d0, 0xa9804, 0xa9836, 0xa9840, 0xa9b34, 0xa9b46, - 0xa9b64, 0xa9ba6, 0xa9bc4, 0xa9be6, 0xa9c04, 0xa9c10, - 0xa9e54, 0xa9e60, 0xaa294, 0xaa2f6, 0xaa314, 0xaa336, - 0xaa354, 0xaa370, 0xaa434, 0xaa440, 0xaa4c4, 0xaa4d6, - 0xaa4e0, 0xaa7c4, 0xaa7d0, 0xaab04, 0xaab10, 0xaab24, - 0xaab50, 0xaab74, 0xaab90, 0xaabe4, 0xaac00, 0xaac14, - 0xaac20, 0xaaeb6, 0xaaec4, 0xaaee6, 0xaaf00, 0xaaf56, - 0xaaf64, 0xaaf70, 0xabe36, 0xabe54, 0xabe66, 0xabe84, - 0xabe96, 0xabeb0, 0xabec6, 0xabed4, 0xabee0, 0xac00b, - 0xac01c, 0xac1cb, 0xac1dc, 0xac38b, 0xac39c, 0xac54b, - 0xac55c, 0xac70b, 0xac71c, 0xac8cb, 0xac8dc, 0xaca8b, - 0xaca9c, 0xacc4b, 0xacc5c, 0xace0b, 0xace1c, 0xacfcb, - 0xacfdc, 0xad18b, 0xad19c, 0xad34b, 0xad35c, 0xad50b, - 0xad51c, 0xad6cb, 0xad6dc, 0xad88b, 0xad89c, 0xada4b, - 0xada5c, 0xadc0b, 0xadc1c, 0xaddcb, 0xadddc, 0xadf8b, - 0xadf9c, 0xae14b, 0xae15c, 0xae30b, 0xae31c, 0xae4cb, - 0xae4dc, 0xae68b, 0xae69c, 0xae84b, 0xae85c, 0xaea0b, - 0xaea1c, 0xaebcb, 0xaebdc, 0xaed8b, 0xaed9c, 0xaef4b, - 0xaef5c, 0xaf10b, 0xaf11c, 0xaf2cb, 0xaf2dc, 0xaf48b, - 0xaf49c, 0xaf64b, 0xaf65c, 0xaf80b, 0xaf81c, 0xaf9cb, - 0xaf9dc, 0xafb8b, 0xafb9c, 0xafd4b, 0xafd5c, 0xaff0b, - 0xaff1c, 0xb00cb, 0xb00dc, 0xb028b, 0xb029c, 0xb044b, - 0xb045c, 0xb060b, 0xb061c, 0xb07cb, 0xb07dc, 0xb098b, - 0xb099c, 0xb0b4b, 0xb0b5c, 0xb0d0b, 0xb0d1c, 0xb0ecb, - 0xb0edc, 0xb108b, 0xb109c, 0xb124b, 0xb125c, 0xb140b, - 0xb141c, 0xb15cb, 0xb15dc, 0xb178b, 0xb179c, 0xb194b, - 0xb195c, 0xb1b0b, 0xb1b1c, 0xb1ccb, 0xb1cdc, 0xb1e8b, - 0xb1e9c, 0xb204b, 0xb205c, 0xb220b, 0xb221c, 0xb23cb, - 0xb23dc, 0xb258b, 0xb259c, 0xb274b, 0xb275c, 0xb290b, - 0xb291c, 0xb2acb, 0xb2adc, 0xb2c8b, 0xb2c9c, 0xb2e4b, - 0xb2e5c, 0xb300b, 0xb301c, 0xb31cb, 0xb31dc, 0xb338b, - 0xb339c, 0xb354b, 0xb355c, 0xb370b, 0xb371c, 0xb38cb, - 0xb38dc, 0xb3a8b, 0xb3a9c, 0xb3c4b, 0xb3c5c, 0xb3e0b, - 0xb3e1c, 0xb3fcb, 0xb3fdc, 0xb418b, 0xb419c, 0xb434b, - 0xb435c, 0xb450b, 0xb451c, 0xb46cb, 0xb46dc, 0xb488b, - 0xb489c, 0xb4a4b, 0xb4a5c, 0xb4c0b, 0xb4c1c, 0xb4dcb, - 0xb4ddc, 0xb4f8b, 0xb4f9c, 0xb514b, 0xb515c, 0xb530b, - 0xb531c, 0xb54cb, 0xb54dc, 0xb568b, 0xb569c, 0xb584b, - 0xb585c, 0xb5a0b, 0xb5a1c, 0xb5bcb, 0xb5bdc, 0xb5d8b, - 0xb5d9c, 0xb5f4b, 0xb5f5c, 0xb610b, 0xb611c, 0xb62cb, - 0xb62dc, 0xb648b, 0xb649c, 0xb664b, 0xb665c, 0xb680b, - 0xb681c, 0xb69cb, 0xb69dc, 0xb6b8b, 0xb6b9c, 0xb6d4b, - 0xb6d5c, 0xb6f0b, 0xb6f1c, 0xb70cb, 0xb70dc, 0xb728b, - 0xb729c, 0xb744b, 0xb745c, 0xb760b, 0xb761c, 0xb77cb, - 0xb77dc, 0xb798b, 0xb799c, 0xb7b4b, 0xb7b5c, 0xb7d0b, - 0xb7d1c, 0xb7ecb, 0xb7edc, 0xb808b, 0xb809c, 0xb824b, - 0xb825c, 0xb840b, 0xb841c, 0xb85cb, 0xb85dc, 0xb878b, - 0xb879c, 0xb894b, 0xb895c, 0xb8b0b, 0xb8b1c, 0xb8ccb, - 0xb8cdc, 0xb8e8b, 0xb8e9c, 0xb904b, 0xb905c, 0xb920b, - 0xb921c, 0xb93cb, 0xb93dc, 0xb958b, 0xb959c, 0xb974b, - 0xb975c, 0xb990b, 0xb991c, 0xb9acb, 0xb9adc, 0xb9c8b, - 0xb9c9c, 0xb9e4b, 0xb9e5c, 0xba00b, 0xba01c, 0xba1cb, - 0xba1dc, 0xba38b, 0xba39c, 0xba54b, 0xba55c, 0xba70b, - 0xba71c, 0xba8cb, 0xba8dc, 0xbaa8b, 0xbaa9c, 0xbac4b, - 0xbac5c, 0xbae0b, 0xbae1c, 0xbafcb, 0xbafdc, 0xbb18b, - 0xbb19c, 0xbb34b, 0xbb35c, 0xbb50b, 0xbb51c, 0xbb6cb, - 0xbb6dc, 0xbb88b, 0xbb89c, 0xbba4b, 0xbba5c, 0xbbc0b, - 0xbbc1c, 0xbbdcb, 0xbbddc, 0xbbf8b, 0xbbf9c, 0xbc14b, - 0xbc15c, 0xbc30b, 0xbc31c, 0xbc4cb, 0xbc4dc, 0xbc68b, - 0xbc69c, 0xbc84b, 0xbc85c, 0xbca0b, 0xbca1c, 0xbcbcb, - 0xbcbdc, 0xbcd8b, 0xbcd9c, 0xbcf4b, 0xbcf5c, 0xbd10b, - 0xbd11c, 0xbd2cb, 0xbd2dc, 0xbd48b, 0xbd49c, 0xbd64b, - 0xbd65c, 0xbd80b, 0xbd81c, 0xbd9cb, 0xbd9dc, 0xbdb8b, - 0xbdb9c, 0xbdd4b, 0xbdd5c, 0xbdf0b, 0xbdf1c, 0xbe0cb, - 0xbe0dc, 0xbe28b, 0xbe29c, 0xbe44b, 0xbe45c, 0xbe60b, - 0xbe61c, 0xbe7cb, 0xbe7dc, 0xbe98b, 0xbe99c, 0xbeb4b, - 0xbeb5c, 0xbed0b, 0xbed1c, 0xbeecb, 0xbeedc, 0xbf08b, - 0xbf09c, 0xbf24b, 0xbf25c, 0xbf40b, 0xbf41c, 0xbf5cb, - 0xbf5dc, 0xbf78b, 0xbf79c, 0xbf94b, 0xbf95c, 0xbfb0b, - 0xbfb1c, 0xbfccb, 0xbfcdc, 0xbfe8b, 0xbfe9c, 0xc004b, - 0xc005c, 0xc020b, 0xc021c, 0xc03cb, 0xc03dc, 0xc058b, - 0xc059c, 0xc074b, 0xc075c, 0xc090b, 0xc091c, 0xc0acb, - 0xc0adc, 0xc0c8b, 0xc0c9c, 0xc0e4b, 0xc0e5c, 0xc100b, - 0xc101c, 0xc11cb, 0xc11dc, 0xc138b, 0xc139c, 0xc154b, - 0xc155c, 0xc170b, 0xc171c, 0xc18cb, 0xc18dc, 0xc1a8b, - 0xc1a9c, 0xc1c4b, 0xc1c5c, 0xc1e0b, 0xc1e1c, 0xc1fcb, - 0xc1fdc, 0xc218b, 0xc219c, 0xc234b, 0xc235c, 0xc250b, - 0xc251c, 0xc26cb, 0xc26dc, 0xc288b, 0xc289c, 0xc2a4b, - 0xc2a5c, 0xc2c0b, 0xc2c1c, 0xc2dcb, 0xc2ddc, 0xc2f8b, - 0xc2f9c, 0xc314b, 0xc315c, 0xc330b, 0xc331c, 0xc34cb, - 0xc34dc, 0xc368b, 0xc369c, 0xc384b, 0xc385c, 0xc3a0b, - 0xc3a1c, 0xc3bcb, 0xc3bdc, 0xc3d8b, 0xc3d9c, 0xc3f4b, - 0xc3f5c, 0xc410b, 0xc411c, 0xc42cb, 0xc42dc, 0xc448b, - 0xc449c, 0xc464b, 0xc465c, 0xc480b, 0xc481c, 0xc49cb, - 0xc49dc, 0xc4b8b, 0xc4b9c, 0xc4d4b, 0xc4d5c, 0xc4f0b, - 0xc4f1c, 0xc50cb, 0xc50dc, 0xc528b, 0xc529c, 0xc544b, - 0xc545c, 0xc560b, 0xc561c, 0xc57cb, 0xc57dc, 0xc598b, - 0xc599c, 0xc5b4b, 0xc5b5c, 0xc5d0b, 0xc5d1c, 0xc5ecb, - 0xc5edc, 0xc608b, 0xc609c, 0xc624b, 0xc625c, 0xc640b, - 0xc641c, 0xc65cb, 0xc65dc, 0xc678b, 0xc679c, 0xc694b, - 0xc695c, 0xc6b0b, 0xc6b1c, 0xc6ccb, 0xc6cdc, 0xc6e8b, - 0xc6e9c, 0xc704b, 0xc705c, 0xc720b, 0xc721c, 0xc73cb, - 0xc73dc, 0xc758b, 0xc759c, 0xc774b, 0xc775c, 0xc790b, - 0xc791c, 0xc7acb, 0xc7adc, 0xc7c8b, 0xc7c9c, 0xc7e4b, - 0xc7e5c, 0xc800b, 0xc801c, 0xc81cb, 0xc81dc, 0xc838b, - 0xc839c, 0xc854b, 0xc855c, 0xc870b, 0xc871c, 0xc88cb, - 0xc88dc, 0xc8a8b, 0xc8a9c, 0xc8c4b, 0xc8c5c, 0xc8e0b, - 0xc8e1c, 0xc8fcb, 0xc8fdc, 0xc918b, 0xc919c, 0xc934b, - 0xc935c, 0xc950b, 0xc951c, 0xc96cb, 0xc96dc, 0xc988b, - 0xc989c, 0xc9a4b, 0xc9a5c, 0xc9c0b, 0xc9c1c, 0xc9dcb, - 0xc9ddc, 0xc9f8b, 0xc9f9c, 0xca14b, 0xca15c, 0xca30b, - 0xca31c, 0xca4cb, 0xca4dc, 0xca68b, 0xca69c, 0xca84b, - 0xca85c, 0xcaa0b, 0xcaa1c, 0xcabcb, 0xcabdc, 0xcad8b, - 0xcad9c, 0xcaf4b, 0xcaf5c, 0xcb10b, 0xcb11c, 0xcb2cb, - 0xcb2dc, 0xcb48b, 0xcb49c, 0xcb64b, 0xcb65c, 0xcb80b, - 0xcb81c, 0xcb9cb, 0xcb9dc, 0xcbb8b, 0xcbb9c, 0xcbd4b, - 0xcbd5c, 0xcbf0b, 0xcbf1c, 0xcc0cb, 0xcc0dc, 0xcc28b, - 0xcc29c, 0xcc44b, 0xcc45c, 0xcc60b, 0xcc61c, 0xcc7cb, - 0xcc7dc, 0xcc98b, 0xcc99c, 0xccb4b, 0xccb5c, 0xccd0b, - 0xccd1c, 0xccecb, 0xccedc, 0xcd08b, 0xcd09c, 0xcd24b, - 0xcd25c, 0xcd40b, 0xcd41c, 0xcd5cb, 0xcd5dc, 0xcd78b, - 0xcd79c, 0xcd94b, 0xcd95c, 0xcdb0b, 0xcdb1c, 0xcdccb, - 0xcdcdc, 0xcde8b, 0xcde9c, 0xce04b, 0xce05c, 0xce20b, - 0xce21c, 0xce3cb, 0xce3dc, 0xce58b, 0xce59c, 0xce74b, - 0xce75c, 0xce90b, 0xce91c, 0xceacb, 0xceadc, 0xcec8b, - 0xcec9c, 0xcee4b, 0xcee5c, 0xcf00b, 0xcf01c, 0xcf1cb, - 0xcf1dc, 0xcf38b, 0xcf39c, 0xcf54b, 0xcf55c, 0xcf70b, - 0xcf71c, 0xcf8cb, 0xcf8dc, 0xcfa8b, 0xcfa9c, 0xcfc4b, - 0xcfc5c, 0xcfe0b, 0xcfe1c, 0xcffcb, 0xcffdc, 0xd018b, - 0xd019c, 0xd034b, 0xd035c, 0xd050b, 0xd051c, 0xd06cb, - 0xd06dc, 0xd088b, 0xd089c, 0xd0a4b, 0xd0a5c, 0xd0c0b, - 0xd0c1c, 0xd0dcb, 0xd0ddc, 0xd0f8b, 0xd0f9c, 0xd114b, - 0xd115c, 0xd130b, 0xd131c, 0xd14cb, 0xd14dc, 0xd168b, - 0xd169c, 0xd184b, 0xd185c, 0xd1a0b, 0xd1a1c, 0xd1bcb, - 0xd1bdc, 0xd1d8b, 0xd1d9c, 0xd1f4b, 0xd1f5c, 0xd210b, - 0xd211c, 0xd22cb, 0xd22dc, 0xd248b, 0xd249c, 0xd264b, - 0xd265c, 0xd280b, 0xd281c, 0xd29cb, 0xd29dc, 0xd2b8b, - 0xd2b9c, 0xd2d4b, 0xd2d5c, 0xd2f0b, 0xd2f1c, 0xd30cb, - 0xd30dc, 0xd328b, 0xd329c, 0xd344b, 0xd345c, 0xd360b, - 0xd361c, 0xd37cb, 0xd37dc, 0xd398b, 0xd399c, 0xd3b4b, - 0xd3b5c, 0xd3d0b, 0xd3d1c, 0xd3ecb, 0xd3edc, 0xd408b, - 0xd409c, 0xd424b, 0xd425c, 0xd440b, 0xd441c, 0xd45cb, - 0xd45dc, 0xd478b, 0xd479c, 0xd494b, 0xd495c, 0xd4b0b, - 0xd4b1c, 0xd4ccb, 0xd4cdc, 0xd4e8b, 0xd4e9c, 0xd504b, - 0xd505c, 0xd520b, 0xd521c, 0xd53cb, 0xd53dc, 0xd558b, - 0xd559c, 0xd574b, 0xd575c, 0xd590b, 0xd591c, 0xd5acb, - 0xd5adc, 0xd5c8b, 0xd5c9c, 0xd5e4b, 0xd5e5c, 0xd600b, - 0xd601c, 0xd61cb, 0xd61dc, 0xd638b, 0xd639c, 0xd654b, - 0xd655c, 0xd670b, 0xd671c, 0xd68cb, 0xd68dc, 0xd6a8b, - 0xd6a9c, 0xd6c4b, 0xd6c5c, 0xd6e0b, 0xd6e1c, 0xd6fcb, - 0xd6fdc, 0xd718b, 0xd719c, 0xd734b, 0xd735c, 0xd750b, - 0xd751c, 0xd76cb, 0xd76dc, 0xd788b, 0xd789c, 0xd7a40, - 0xd7b08, 0xd7c70, 0xd7cb9, 0xd7fc0, 0xfb1e4, 0xfb1f0, - 0xfe004, 0xfe100, 0xfe204, 0xfe300, 0xfeff1, 0xff000, - 0xff9e4, 0xffa00, 0xfff01, 0xfffc0, 0x101fd4, 0x101fe0, - 0x102e04, 0x102e10, 0x103764, 0x1037b0, 0x10a014, 0x10a040, - 0x10a054, 0x10a070, 0x10a0c4, 0x10a100, 0x10a384, 0x10a3b0, - 0x10a3f4, 0x10a400, 0x10ae54, 0x10ae70, 0x10d244, 0x10d280, - 0x10d694, 0x10d6e0, 0x10eab4, 0x10ead0, 0x10efc4, 0x10f000, - 0x10f464, 0x10f510, 0x10f824, 0x10f860, 0x110006, 0x110014, - 0x110026, 0x110030, 0x110384, 0x110470, 0x110704, 0x110710, - 0x110734, 0x110750, 0x1107f4, 0x110826, 0x110830, 0x110b06, - 0x110b34, 0x110b76, 0x110b94, 0x110bb0, 0x110bd5, 0x110be0, - 0x110c24, 0x110c30, 0x110cd5, 0x110ce0, 0x111004, 0x111030, - 0x111274, 0x1112c6, 0x1112d4, 0x111350, 0x111456, 0x111470, - 0x111734, 0x111740, 0x111804, 0x111826, 0x111830, 0x111b36, - 0x111b64, 0x111bf6, 0x111c04, 0x111c10, 0x111c25, 0x111c40, - 0x111c94, 0x111cd0, 0x111ce6, 0x111cf4, 0x111d00, 0x1122c6, - 0x1122f4, 0x112326, 0x112344, 0x112380, 0x1123e4, 0x1123f0, - 0x112414, 0x112420, 0x112df4, 0x112e06, 0x112e34, 0x112eb0, - 0x113004, 0x113026, 0x113040, 0x1133b4, 0x1133d0, 0x1133e4, - 0x1133f6, 0x113404, 0x113416, 0x113450, 0x113476, 0x113490, - 0x1134b6, 0x1134d4, 0x1134e0, 0x113574, 0x113580, 0x113626, - 0x113640, 0x113664, 0x1136d0, 0x113704, 0x113750, 0x113b84, - 0x113b96, 0x113bb4, 0x113c10, 0x113c24, 0x113c30, 0x113c54, - 0x113c60, 0x113c74, 0x113ca6, 0x113cb0, 0x113cc6, 0x113ce4, - 0x113d15, 0x113d24, 0x113d30, 0x113e14, 0x113e30, 0x114356, - 0x114384, 0x114406, 0x114424, 0x114456, 0x114464, 0x114470, - 0x1145e4, 0x1145f0, 0x114b04, 0x114b16, 0x114b34, 0x114b96, - 0x114ba4, 0x114bb6, 0x114bd4, 0x114be6, 0x114bf4, 0x114c16, - 0x114c24, 0x114c40, 0x115af4, 0x115b06, 0x115b24, 0x115b60, - 0x115b86, 0x115bc4, 0x115be6, 0x115bf4, 0x115c10, 0x115dc4, - 0x115de0, 0x116306, 0x116334, 0x1163b6, 0x1163d4, 0x1163e6, - 0x1163f4, 0x116410, 0x116ab4, 0x116ac6, 0x116ad4, 0x116ae6, - 0x116b04, 0x116b80, 0x1171d4, 0x1171e6, 0x1171f4, 0x117200, - 0x117224, 0x117266, 0x117274, 0x1172c0, 0x1182c6, 0x1182f4, - 0x118386, 0x118394, 0x1183b0, 0x119304, 0x119316, 0x119360, - 0x119376, 0x119390, 0x1193b4, 0x1193f5, 0x119406, 0x119415, - 0x119426, 0x119434, 0x119440, 0x119d16, 0x119d44, 0x119d80, - 0x119da4, 0x119dc6, 0x119e04, 0x119e10, 0x119e46, 0x119e50, - 0x11a014, 0x11a0b0, 0x11a334, 0x11a396, 0x11a3a5, 0x11a3b4, - 0x11a3f0, 0x11a474, 0x11a480, 0x11a514, 0x11a576, 0x11a594, - 0x11a5c0, 0x11a845, 0x11a8a4, 0x11a976, 0x11a984, 0x11a9a0, - 0x11c2f6, 0x11c304, 0x11c370, 0x11c384, 0x11c3e6, 0x11c3f4, - 0x11c400, 0x11c924, 0x11ca80, 0x11ca96, 0x11caa4, 0x11cb16, - 0x11cb24, 0x11cb46, 0x11cb54, 0x11cb70, 0x11d314, 0x11d370, - 0x11d3a4, 0x11d3b0, 0x11d3c4, 0x11d3e0, 0x11d3f4, 0x11d465, - 0x11d474, 0x11d480, 0x11d8a6, 0x11d8f0, 0x11d904, 0x11d920, - 0x11d936, 0x11d954, 0x11d966, 0x11d974, 0x11d980, 0x11ef34, - 0x11ef56, 0x11ef70, 0x11f004, 0x11f025, 0x11f036, 0x11f040, - 0x11f346, 0x11f364, 0x11f3b0, 0x11f3e6, 0x11f404, 0x11f430, - 0x11f5a4, 0x11f5b0, 0x134301, 0x134404, 0x134410, 0x134474, - 0x134560, 0x1611e4, 0x1612a6, 0x1612d4, 0x161300, 0x16af04, - 0x16af50, 0x16b304, 0x16b370, 0x16d638, 0x16d640, 0x16d678, - 0x16d6b0, 0x16f4f4, 0x16f500, 0x16f516, 0x16f880, 0x16f8f4, - 0x16f930, 0x16fe44, 0x16fe50, 0x16ff04, 0x16ff20, 0x1bc9d4, - 0x1bc9f0, 0x1bca01, 0x1bca40, 0x1cf004, 0x1cf2e0, 0x1cf304, - 0x1cf470, 0x1d1654, 0x1d16a0, 0x1d16d4, 0x1d1731, 0x1d17b4, - 0x1d1830, 0x1d1854, 0x1d18c0, 0x1d1aa4, 0x1d1ae0, 0x1d2424, - 0x1d2450, 0x1da004, 0x1da370, 0x1da3b4, 0x1da6d0, 0x1da754, - 0x1da760, 0x1da844, 0x1da850, 0x1da9b4, 0x1daa00, 0x1daa14, - 0x1dab00, 0x1e0004, 0x1e0070, 0x1e0084, 0x1e0190, 0x1e01b4, - 0x1e0220, 0x1e0234, 0x1e0250, 0x1e0264, 0x1e02b0, 0x1e08f4, - 0x1e0900, 0x1e1304, 0x1e1370, 0x1e2ae4, 0x1e2af0, 0x1e2ec4, - 0x1e2f00, 0x1e4ec4, 0x1e4f00, 0x1e5ee4, 0x1e5f00, 0x1e8d04, - 0x1e8d70, 0x1e9444, 0x1e94b0, 0x1f1e6d, 0x1f2000, 0x1f3fb4, - 0x1f4000, 0xe00001, 0xe00204, 0xe00801, 0xe01004, 0xe01f01, - 0xe10000, + 0x1a734, 0x1a7d0, 0x1a7f4, 0x1a800, 0x1ab04, 0x1ade0, + 0x1ae04, 0x1aec0, 0x1b004, 0x1b046, 0x1b050, 0x1b344, + 0x1b3e6, 0x1b424, 0x1b450, 0x1b6b4, 0x1b740, 0x1b804, + 0x1b826, 0x1b830, 0x1ba16, 0x1ba24, 0x1ba66, 0x1ba84, + 0x1bae0, 0x1be64, 0x1be76, 0x1be84, 0x1bea6, 0x1bed4, + 0x1bee6, 0x1bef4, 0x1bf40, 0x1c246, 0x1c2c4, 0x1c346, + 0x1c364, 0x1c380, 0x1cd04, 0x1cd30, 0x1cd44, 0x1ce16, + 0x1ce24, 0x1ce90, 0x1ced4, 0x1cee0, 0x1cf44, 0x1cf50, + 0x1cf76, 0x1cf84, 0x1cfa0, 0x1dc04, 0x1e000, 0x200b1, + 0x200c4, 0x200da, 0x200e1, 0x20100, 0x20281, 0x202f0, + 0x20601, 0x20700, 0x20d04, 0x20f10, 0x2cef4, 0x2cf20, + 0x2d7f4, 0x2d800, 0x2de04, 0x2e000, 0x302a4, 0x30300, + 0x30994, 0x309b0, 0xa66f4, 0xa6730, 0xa6744, 0xa67e0, + 0xa69e4, 0xa6a00, 0xa6f04, 0xa6f20, 0xa8024, 0xa8030, + 0xa8064, 0xa8070, 0xa80b4, 0xa80c0, 0xa8236, 0xa8254, + 0xa8276, 0xa8280, 0xa82c4, 0xa82d0, 0xa8806, 0xa8820, + 0xa8b46, 0xa8c44, 0xa8c60, 0xa8e04, 0xa8f20, 0xa8ff4, + 0xa9000, 0xa9264, 0xa92e0, 0xa9474, 0xa9526, 0xa9534, + 0xa9540, 0xa9607, 0xa97d0, 0xa9804, 0xa9836, 0xa9840, + 0xa9b34, 0xa9b46, 0xa9b64, 0xa9ba6, 0xa9bc4, 0xa9be6, + 0xa9c04, 0xa9c10, 0xa9e54, 0xa9e60, 0xaa294, 0xaa2f6, + 0xaa314, 0xaa336, 0xaa354, 0xaa370, 0xaa434, 0xaa440, + 0xaa4c4, 0xaa4d6, 0xaa4e0, 0xaa7c4, 0xaa7d0, 0xaab04, + 0xaab10, 0xaab24, 0xaab50, 0xaab74, 0xaab90, 0xaabe4, + 0xaac00, 0xaac14, 0xaac20, 0xaaeb6, 0xaaec4, 0xaaee6, + 0xaaf00, 0xaaf56, 0xaaf64, 0xaaf70, 0xabe36, 0xabe54, + 0xabe66, 0xabe84, 0xabe96, 0xabeb0, 0xabec6, 0xabed4, + 0xabee0, 0xac00b, 0xac01c, 0xac1cb, 0xac1dc, 0xac38b, + 0xac39c, 0xac54b, 0xac55c, 0xac70b, 0xac71c, 0xac8cb, + 0xac8dc, 0xaca8b, 0xaca9c, 0xacc4b, 0xacc5c, 0xace0b, + 0xace1c, 0xacfcb, 0xacfdc, 0xad18b, 0xad19c, 0xad34b, + 0xad35c, 0xad50b, 0xad51c, 0xad6cb, 0xad6dc, 0xad88b, + 0xad89c, 0xada4b, 0xada5c, 0xadc0b, 0xadc1c, 0xaddcb, + 0xadddc, 0xadf8b, 0xadf9c, 0xae14b, 0xae15c, 0xae30b, + 0xae31c, 0xae4cb, 0xae4dc, 0xae68b, 0xae69c, 0xae84b, + 0xae85c, 0xaea0b, 0xaea1c, 0xaebcb, 0xaebdc, 0xaed8b, + 0xaed9c, 0xaef4b, 0xaef5c, 0xaf10b, 0xaf11c, 0xaf2cb, + 0xaf2dc, 0xaf48b, 0xaf49c, 0xaf64b, 0xaf65c, 0xaf80b, + 0xaf81c, 0xaf9cb, 0xaf9dc, 0xafb8b, 0xafb9c, 0xafd4b, + 0xafd5c, 0xaff0b, 0xaff1c, 0xb00cb, 0xb00dc, 0xb028b, + 0xb029c, 0xb044b, 0xb045c, 0xb060b, 0xb061c, 0xb07cb, + 0xb07dc, 0xb098b, 0xb099c, 0xb0b4b, 0xb0b5c, 0xb0d0b, + 0xb0d1c, 0xb0ecb, 0xb0edc, 0xb108b, 0xb109c, 0xb124b, + 0xb125c, 0xb140b, 0xb141c, 0xb15cb, 0xb15dc, 0xb178b, + 0xb179c, 0xb194b, 0xb195c, 0xb1b0b, 0xb1b1c, 0xb1ccb, + 0xb1cdc, 0xb1e8b, 0xb1e9c, 0xb204b, 0xb205c, 0xb220b, + 0xb221c, 0xb23cb, 0xb23dc, 0xb258b, 0xb259c, 0xb274b, + 0xb275c, 0xb290b, 0xb291c, 0xb2acb, 0xb2adc, 0xb2c8b, + 0xb2c9c, 0xb2e4b, 0xb2e5c, 0xb300b, 0xb301c, 0xb31cb, + 0xb31dc, 0xb338b, 0xb339c, 0xb354b, 0xb355c, 0xb370b, + 0xb371c, 0xb38cb, 0xb38dc, 0xb3a8b, 0xb3a9c, 0xb3c4b, + 0xb3c5c, 0xb3e0b, 0xb3e1c, 0xb3fcb, 0xb3fdc, 0xb418b, + 0xb419c, 0xb434b, 0xb435c, 0xb450b, 0xb451c, 0xb46cb, + 0xb46dc, 0xb488b, 0xb489c, 0xb4a4b, 0xb4a5c, 0xb4c0b, + 0xb4c1c, 0xb4dcb, 0xb4ddc, 0xb4f8b, 0xb4f9c, 0xb514b, + 0xb515c, 0xb530b, 0xb531c, 0xb54cb, 0xb54dc, 0xb568b, + 0xb569c, 0xb584b, 0xb585c, 0xb5a0b, 0xb5a1c, 0xb5bcb, + 0xb5bdc, 0xb5d8b, 0xb5d9c, 0xb5f4b, 0xb5f5c, 0xb610b, + 0xb611c, 0xb62cb, 0xb62dc, 0xb648b, 0xb649c, 0xb664b, + 0xb665c, 0xb680b, 0xb681c, 0xb69cb, 0xb69dc, 0xb6b8b, + 0xb6b9c, 0xb6d4b, 0xb6d5c, 0xb6f0b, 0xb6f1c, 0xb70cb, + 0xb70dc, 0xb728b, 0xb729c, 0xb744b, 0xb745c, 0xb760b, + 0xb761c, 0xb77cb, 0xb77dc, 0xb798b, 0xb799c, 0xb7b4b, + 0xb7b5c, 0xb7d0b, 0xb7d1c, 0xb7ecb, 0xb7edc, 0xb808b, + 0xb809c, 0xb824b, 0xb825c, 0xb840b, 0xb841c, 0xb85cb, + 0xb85dc, 0xb878b, 0xb879c, 0xb894b, 0xb895c, 0xb8b0b, + 0xb8b1c, 0xb8ccb, 0xb8cdc, 0xb8e8b, 0xb8e9c, 0xb904b, + 0xb905c, 0xb920b, 0xb921c, 0xb93cb, 0xb93dc, 0xb958b, + 0xb959c, 0xb974b, 0xb975c, 0xb990b, 0xb991c, 0xb9acb, + 0xb9adc, 0xb9c8b, 0xb9c9c, 0xb9e4b, 0xb9e5c, 0xba00b, + 0xba01c, 0xba1cb, 0xba1dc, 0xba38b, 0xba39c, 0xba54b, + 0xba55c, 0xba70b, 0xba71c, 0xba8cb, 0xba8dc, 0xbaa8b, + 0xbaa9c, 0xbac4b, 0xbac5c, 0xbae0b, 0xbae1c, 0xbafcb, + 0xbafdc, 0xbb18b, 0xbb19c, 0xbb34b, 0xbb35c, 0xbb50b, + 0xbb51c, 0xbb6cb, 0xbb6dc, 0xbb88b, 0xbb89c, 0xbba4b, + 0xbba5c, 0xbbc0b, 0xbbc1c, 0xbbdcb, 0xbbddc, 0xbbf8b, + 0xbbf9c, 0xbc14b, 0xbc15c, 0xbc30b, 0xbc31c, 0xbc4cb, + 0xbc4dc, 0xbc68b, 0xbc69c, 0xbc84b, 0xbc85c, 0xbca0b, + 0xbca1c, 0xbcbcb, 0xbcbdc, 0xbcd8b, 0xbcd9c, 0xbcf4b, + 0xbcf5c, 0xbd10b, 0xbd11c, 0xbd2cb, 0xbd2dc, 0xbd48b, + 0xbd49c, 0xbd64b, 0xbd65c, 0xbd80b, 0xbd81c, 0xbd9cb, + 0xbd9dc, 0xbdb8b, 0xbdb9c, 0xbdd4b, 0xbdd5c, 0xbdf0b, + 0xbdf1c, 0xbe0cb, 0xbe0dc, 0xbe28b, 0xbe29c, 0xbe44b, + 0xbe45c, 0xbe60b, 0xbe61c, 0xbe7cb, 0xbe7dc, 0xbe98b, + 0xbe99c, 0xbeb4b, 0xbeb5c, 0xbed0b, 0xbed1c, 0xbeecb, + 0xbeedc, 0xbf08b, 0xbf09c, 0xbf24b, 0xbf25c, 0xbf40b, + 0xbf41c, 0xbf5cb, 0xbf5dc, 0xbf78b, 0xbf79c, 0xbf94b, + 0xbf95c, 0xbfb0b, 0xbfb1c, 0xbfccb, 0xbfcdc, 0xbfe8b, + 0xbfe9c, 0xc004b, 0xc005c, 0xc020b, 0xc021c, 0xc03cb, + 0xc03dc, 0xc058b, 0xc059c, 0xc074b, 0xc075c, 0xc090b, + 0xc091c, 0xc0acb, 0xc0adc, 0xc0c8b, 0xc0c9c, 0xc0e4b, + 0xc0e5c, 0xc100b, 0xc101c, 0xc11cb, 0xc11dc, 0xc138b, + 0xc139c, 0xc154b, 0xc155c, 0xc170b, 0xc171c, 0xc18cb, + 0xc18dc, 0xc1a8b, 0xc1a9c, 0xc1c4b, 0xc1c5c, 0xc1e0b, + 0xc1e1c, 0xc1fcb, 0xc1fdc, 0xc218b, 0xc219c, 0xc234b, + 0xc235c, 0xc250b, 0xc251c, 0xc26cb, 0xc26dc, 0xc288b, + 0xc289c, 0xc2a4b, 0xc2a5c, 0xc2c0b, 0xc2c1c, 0xc2dcb, + 0xc2ddc, 0xc2f8b, 0xc2f9c, 0xc314b, 0xc315c, 0xc330b, + 0xc331c, 0xc34cb, 0xc34dc, 0xc368b, 0xc369c, 0xc384b, + 0xc385c, 0xc3a0b, 0xc3a1c, 0xc3bcb, 0xc3bdc, 0xc3d8b, + 0xc3d9c, 0xc3f4b, 0xc3f5c, 0xc410b, 0xc411c, 0xc42cb, + 0xc42dc, 0xc448b, 0xc449c, 0xc464b, 0xc465c, 0xc480b, + 0xc481c, 0xc49cb, 0xc49dc, 0xc4b8b, 0xc4b9c, 0xc4d4b, + 0xc4d5c, 0xc4f0b, 0xc4f1c, 0xc50cb, 0xc50dc, 0xc528b, + 0xc529c, 0xc544b, 0xc545c, 0xc560b, 0xc561c, 0xc57cb, + 0xc57dc, 0xc598b, 0xc599c, 0xc5b4b, 0xc5b5c, 0xc5d0b, + 0xc5d1c, 0xc5ecb, 0xc5edc, 0xc608b, 0xc609c, 0xc624b, + 0xc625c, 0xc640b, 0xc641c, 0xc65cb, 0xc65dc, 0xc678b, + 0xc679c, 0xc694b, 0xc695c, 0xc6b0b, 0xc6b1c, 0xc6ccb, + 0xc6cdc, 0xc6e8b, 0xc6e9c, 0xc704b, 0xc705c, 0xc720b, + 0xc721c, 0xc73cb, 0xc73dc, 0xc758b, 0xc759c, 0xc774b, + 0xc775c, 0xc790b, 0xc791c, 0xc7acb, 0xc7adc, 0xc7c8b, + 0xc7c9c, 0xc7e4b, 0xc7e5c, 0xc800b, 0xc801c, 0xc81cb, + 0xc81dc, 0xc838b, 0xc839c, 0xc854b, 0xc855c, 0xc870b, + 0xc871c, 0xc88cb, 0xc88dc, 0xc8a8b, 0xc8a9c, 0xc8c4b, + 0xc8c5c, 0xc8e0b, 0xc8e1c, 0xc8fcb, 0xc8fdc, 0xc918b, + 0xc919c, 0xc934b, 0xc935c, 0xc950b, 0xc951c, 0xc96cb, + 0xc96dc, 0xc988b, 0xc989c, 0xc9a4b, 0xc9a5c, 0xc9c0b, + 0xc9c1c, 0xc9dcb, 0xc9ddc, 0xc9f8b, 0xc9f9c, 0xca14b, + 0xca15c, 0xca30b, 0xca31c, 0xca4cb, 0xca4dc, 0xca68b, + 0xca69c, 0xca84b, 0xca85c, 0xcaa0b, 0xcaa1c, 0xcabcb, + 0xcabdc, 0xcad8b, 0xcad9c, 0xcaf4b, 0xcaf5c, 0xcb10b, + 0xcb11c, 0xcb2cb, 0xcb2dc, 0xcb48b, 0xcb49c, 0xcb64b, + 0xcb65c, 0xcb80b, 0xcb81c, 0xcb9cb, 0xcb9dc, 0xcbb8b, + 0xcbb9c, 0xcbd4b, 0xcbd5c, 0xcbf0b, 0xcbf1c, 0xcc0cb, + 0xcc0dc, 0xcc28b, 0xcc29c, 0xcc44b, 0xcc45c, 0xcc60b, + 0xcc61c, 0xcc7cb, 0xcc7dc, 0xcc98b, 0xcc99c, 0xccb4b, + 0xccb5c, 0xccd0b, 0xccd1c, 0xccecb, 0xccedc, 0xcd08b, + 0xcd09c, 0xcd24b, 0xcd25c, 0xcd40b, 0xcd41c, 0xcd5cb, + 0xcd5dc, 0xcd78b, 0xcd79c, 0xcd94b, 0xcd95c, 0xcdb0b, + 0xcdb1c, 0xcdccb, 0xcdcdc, 0xcde8b, 0xcde9c, 0xce04b, + 0xce05c, 0xce20b, 0xce21c, 0xce3cb, 0xce3dc, 0xce58b, + 0xce59c, 0xce74b, 0xce75c, 0xce90b, 0xce91c, 0xceacb, + 0xceadc, 0xcec8b, 0xcec9c, 0xcee4b, 0xcee5c, 0xcf00b, + 0xcf01c, 0xcf1cb, 0xcf1dc, 0xcf38b, 0xcf39c, 0xcf54b, + 0xcf55c, 0xcf70b, 0xcf71c, 0xcf8cb, 0xcf8dc, 0xcfa8b, + 0xcfa9c, 0xcfc4b, 0xcfc5c, 0xcfe0b, 0xcfe1c, 0xcffcb, + 0xcffdc, 0xd018b, 0xd019c, 0xd034b, 0xd035c, 0xd050b, + 0xd051c, 0xd06cb, 0xd06dc, 0xd088b, 0xd089c, 0xd0a4b, + 0xd0a5c, 0xd0c0b, 0xd0c1c, 0xd0dcb, 0xd0ddc, 0xd0f8b, + 0xd0f9c, 0xd114b, 0xd115c, 0xd130b, 0xd131c, 0xd14cb, + 0xd14dc, 0xd168b, 0xd169c, 0xd184b, 0xd185c, 0xd1a0b, + 0xd1a1c, 0xd1bcb, 0xd1bdc, 0xd1d8b, 0xd1d9c, 0xd1f4b, + 0xd1f5c, 0xd210b, 0xd211c, 0xd22cb, 0xd22dc, 0xd248b, + 0xd249c, 0xd264b, 0xd265c, 0xd280b, 0xd281c, 0xd29cb, + 0xd29dc, 0xd2b8b, 0xd2b9c, 0xd2d4b, 0xd2d5c, 0xd2f0b, + 0xd2f1c, 0xd30cb, 0xd30dc, 0xd328b, 0xd329c, 0xd344b, + 0xd345c, 0xd360b, 0xd361c, 0xd37cb, 0xd37dc, 0xd398b, + 0xd399c, 0xd3b4b, 0xd3b5c, 0xd3d0b, 0xd3d1c, 0xd3ecb, + 0xd3edc, 0xd408b, 0xd409c, 0xd424b, 0xd425c, 0xd440b, + 0xd441c, 0xd45cb, 0xd45dc, 0xd478b, 0xd479c, 0xd494b, + 0xd495c, 0xd4b0b, 0xd4b1c, 0xd4ccb, 0xd4cdc, 0xd4e8b, + 0xd4e9c, 0xd504b, 0xd505c, 0xd520b, 0xd521c, 0xd53cb, + 0xd53dc, 0xd558b, 0xd559c, 0xd574b, 0xd575c, 0xd590b, + 0xd591c, 0xd5acb, 0xd5adc, 0xd5c8b, 0xd5c9c, 0xd5e4b, + 0xd5e5c, 0xd600b, 0xd601c, 0xd61cb, 0xd61dc, 0xd638b, + 0xd639c, 0xd654b, 0xd655c, 0xd670b, 0xd671c, 0xd68cb, + 0xd68dc, 0xd6a8b, 0xd6a9c, 0xd6c4b, 0xd6c5c, 0xd6e0b, + 0xd6e1c, 0xd6fcb, 0xd6fdc, 0xd718b, 0xd719c, 0xd734b, + 0xd735c, 0xd750b, 0xd751c, 0xd76cb, 0xd76dc, 0xd788b, + 0xd789c, 0xd7a40, 0xd7b08, 0xd7c70, 0xd7cb9, 0xd7fc0, + 0xfb1e4, 0xfb1f0, 0xfe004, 0xfe100, 0xfe204, 0xfe300, + 0xfeff1, 0xff000, 0xff9e4, 0xffa00, 0xfff01, 0xfffc0, + 0x101fd4, 0x101fe0, 0x102e04, 0x102e10, 0x103764, 0x1037b0, + 0x10a014, 0x10a040, 0x10a054, 0x10a070, 0x10a0c4, 0x10a100, + 0x10a384, 0x10a3b0, 0x10a3f4, 0x10a400, 0x10ae54, 0x10ae70, + 0x10d244, 0x10d280, 0x10d694, 0x10d6e0, 0x10eab4, 0x10ead0, + 0x10efa4, 0x10f000, 0x10f464, 0x10f510, 0x10f824, 0x10f860, + 0x110006, 0x110014, 0x110026, 0x110030, 0x110384, 0x110470, + 0x110704, 0x110710, 0x110734, 0x110750, 0x1107f4, 0x110826, + 0x110830, 0x110b06, 0x110b34, 0x110b76, 0x110b94, 0x110bb0, + 0x110bd5, 0x110be0, 0x110c24, 0x110c30, 0x110cd5, 0x110ce0, + 0x111004, 0x111030, 0x111274, 0x1112c6, 0x1112d4, 0x111350, + 0x111456, 0x111470, 0x111734, 0x111740, 0x111804, 0x111826, + 0x111830, 0x111b36, 0x111b64, 0x111bf6, 0x111c04, 0x111c10, + 0x111c25, 0x111c40, 0x111c94, 0x111cd0, 0x111ce6, 0x111cf4, + 0x111d00, 0x1122c6, 0x1122f4, 0x112326, 0x112344, 0x112380, + 0x1123e4, 0x1123f0, 0x112414, 0x112420, 0x112df4, 0x112e06, + 0x112e34, 0x112eb0, 0x113004, 0x113026, 0x113040, 0x1133b4, + 0x1133d0, 0x1133e4, 0x1133f6, 0x113404, 0x113416, 0x113450, + 0x113476, 0x113490, 0x1134b6, 0x1134d4, 0x1134e0, 0x113574, + 0x113580, 0x113626, 0x113640, 0x113664, 0x1136d0, 0x113704, + 0x113750, 0x113b84, 0x113b96, 0x113bb4, 0x113c10, 0x113c24, + 0x113c30, 0x113c54, 0x113c60, 0x113c74, 0x113ca6, 0x113cb0, + 0x113cc6, 0x113ce4, 0x113d15, 0x113d24, 0x113d30, 0x113e14, + 0x113e30, 0x114356, 0x114384, 0x114406, 0x114424, 0x114456, + 0x114464, 0x114470, 0x1145e4, 0x1145f0, 0x114b04, 0x114b16, + 0x114b34, 0x114b96, 0x114ba4, 0x114bb6, 0x114bd4, 0x114be6, + 0x114bf4, 0x114c16, 0x114c24, 0x114c40, 0x115af4, 0x115b06, + 0x115b24, 0x115b60, 0x115b86, 0x115bc4, 0x115be6, 0x115bf4, + 0x115c10, 0x115dc4, 0x115de0, 0x116306, 0x116334, 0x1163b6, + 0x1163d4, 0x1163e6, 0x1163f4, 0x116410, 0x116ab4, 0x116ac6, + 0x116ad4, 0x116ae6, 0x116b04, 0x116b80, 0x1171d4, 0x1171e6, + 0x1171f4, 0x117200, 0x117224, 0x117266, 0x117274, 0x1172c0, + 0x1182c6, 0x1182f4, 0x118386, 0x118394, 0x1183b0, 0x119304, + 0x119316, 0x119360, 0x119376, 0x119390, 0x1193b4, 0x1193f5, + 0x119406, 0x119415, 0x119426, 0x119434, 0x119440, 0x119d16, + 0x119d44, 0x119d80, 0x119da4, 0x119dc6, 0x119e04, 0x119e10, + 0x119e46, 0x119e50, 0x11a014, 0x11a0b0, 0x11a334, 0x11a396, + 0x11a3a0, 0x11a3b4, 0x11a3f0, 0x11a474, 0x11a480, 0x11a514, + 0x11a576, 0x11a594, 0x11a5c0, 0x11a845, 0x11a8a4, 0x11a976, + 0x11a984, 0x11a9a0, 0x11b604, 0x11b616, 0x11b624, 0x11b656, + 0x11b664, 0x11b676, 0x11b680, 0x11c2f6, 0x11c304, 0x11c370, + 0x11c384, 0x11c3e6, 0x11c3f4, 0x11c400, 0x11c924, 0x11ca80, + 0x11ca96, 0x11caa4, 0x11cb16, 0x11cb24, 0x11cb46, 0x11cb54, + 0x11cb70, 0x11d314, 0x11d370, 0x11d3a4, 0x11d3b0, 0x11d3c4, + 0x11d3e0, 0x11d3f4, 0x11d465, 0x11d474, 0x11d480, 0x11d8a6, + 0x11d8f0, 0x11d904, 0x11d920, 0x11d936, 0x11d954, 0x11d966, + 0x11d974, 0x11d980, 0x11ef34, 0x11ef56, 0x11ef70, 0x11f004, + 0x11f025, 0x11f036, 0x11f040, 0x11f346, 0x11f364, 0x11f3b0, + 0x11f3e6, 0x11f404, 0x11f430, 0x11f5a4, 0x11f5b0, 0x134301, + 0x134404, 0x134410, 0x134474, 0x134560, 0x1611e4, 0x1612a6, + 0x1612d4, 0x161300, 0x16af04, 0x16af50, 0x16b304, 0x16b370, + 0x16d638, 0x16d640, 0x16d678, 0x16d6b0, 0x16f4f4, 0x16f500, + 0x16f516, 0x16f880, 0x16f8f4, 0x16f930, 0x16fe44, 0x16fe50, + 0x16ff04, 0x16ff20, 0x1bc9d4, 0x1bc9f0, 0x1bca01, 0x1bca40, + 0x1cf004, 0x1cf2e0, 0x1cf304, 0x1cf470, 0x1d1654, 0x1d16a0, + 0x1d16d4, 0x1d1731, 0x1d17b4, 0x1d1830, 0x1d1854, 0x1d18c0, + 0x1d1aa4, 0x1d1ae0, 0x1d2424, 0x1d2450, 0x1da004, 0x1da370, + 0x1da3b4, 0x1da6d0, 0x1da754, 0x1da760, 0x1da844, 0x1da850, + 0x1da9b4, 0x1daa00, 0x1daa14, 0x1dab00, 0x1e0004, 0x1e0070, + 0x1e0084, 0x1e0190, 0x1e01b4, 0x1e0220, 0x1e0234, 0x1e0250, + 0x1e0264, 0x1e02b0, 0x1e08f4, 0x1e0900, 0x1e1304, 0x1e1370, + 0x1e2ae4, 0x1e2af0, 0x1e2ec4, 0x1e2f00, 0x1e4ec4, 0x1e4f00, + 0x1e5ee4, 0x1e5f00, 0x1e6e34, 0x1e6e40, 0x1e6e64, 0x1e6e70, + 0x1e6ee4, 0x1e6f00, 0x1e6f54, 0x1e6f60, 0x1e8d04, 0x1e8d70, + 0x1e9444, 0x1e94b0, 0x1f1e6d, 0x1f2000, 0x1f3fb4, 0x1f4000, + 0xe00001, 0xe00204, 0xe00801, 0xe01004, 0xe01f01, 0xe10000, }; inline constexpr char32_t __incb_linkers[] = { - 0x094d, 0x09cd, 0x0acd, 0x0b4d, 0x0c4d, 0x0d4d, + 0x094d, 0x09cd, 0x0acd, 0x0b4d, 0x0c4d, 0x0d4d, 0x1039, 0x17d2, 0x1a60, 0x1b44, 0x1bab, 0xa9c0, 0xaaf6, 0x10a3f, 0x11133, 0x113d0, 0x1193e, 0x11a47, 0x11a99, 0x11f42, }; enum class _InCB { _Consonant = 1, _Extend = 2 }; @@ -681,94 +685,109 @@ 0x3cd6, 0x3cd8, 0x3cde, 0x3ce0, 0x3ce6, 0x3ce8, 0x3dc6, 0x3dfc, 0x3e02, 0x3e14, 0x3e1a, 0x3e20, 0x3e36, 0x3e60, 0x3e66, 0x3ef4, 0x3f1a, 0x3f1c, - 0x40b6, 0x40c4, 0x40ca, 0x40e0, 0x40e6, 0x40ec, - 0x40f6, 0x40fc, 0x4162, 0x4168, 0x417a, 0x4184, - 0x41c6, 0x41d4, 0x420a, 0x420c, 0x4216, 0x421c, - 0x4236, 0x4238, 0x4276, 0x4278, 0x4d76, 0x4d80, - 0x5c4a, 0x5c58, 0x5cca, 0x5cd4, 0x5d4a, 0x5d50, - 0x5dca, 0x5dd0, 0x5ed2, 0x5ed8, 0x5ede, 0x5ef8, - 0x5f1a, 0x5f1c, 0x5f26, 0x5f50, 0x5f76, 0x5f78, - 0x602e, 0x6038, 0x603e, 0x6040, 0x6216, 0x621c, - 0x62a6, 0x62a8, 0x6482, 0x648c, 0x649e, 0x64a4, - 0x64ca, 0x64cc, 0x64e6, 0x64f0, 0x685e, 0x6864, - 0x686e, 0x6870, 0x695a, 0x695c, 0x6962, 0x697c, - 0x6982, 0x6984, 0x698a, 0x698c, 0x6996, 0x69b4, - 0x69ce, 0x69f4, 0x69fe, 0x6a00, 0x6ac2, 0x6b3c, - 0x6c02, 0x6c10, 0x6cd2, 0x6cf8, 0x6d0a, 0x6d14, - 0x6dae, 0x6dd0, 0x6e02, 0x6e08, 0x6e8a, 0x6e98, - 0x6ea2, 0x6eb8, 0x6f9a, 0x6f9c, 0x6fa2, 0x6fa8, - 0x6fb6, 0x6fb8, 0x6fbe, 0x6fd0, 0x70b2, 0x70d0, - 0x70da, 0x70e0, 0x7342, 0x734c, 0x7352, 0x7384, - 0x738a, 0x73a4, 0x73b6, 0x73b8, 0x73d2, 0x73d4, - 0x73e2, 0x73e8, 0x7702, 0x7800, 0x8036, 0x8038, - 0x8342, 0x83c4, 0xb3be, 0xb3c8, 0xb5fe, 0xb600, - 0xb782, 0xb800, 0xc0aa, 0xc0c0, 0xc266, 0xc26c, - 0x299be, 0x299cc, 0x299d2, 0x299f8, 0x29a7a, 0x29a80, - 0x29bc2, 0x29bc8, 0x2a00a, 0x2a00c, 0x2a01a, 0x2a01c, - 0x2a02e, 0x2a030, 0x2a096, 0x2a09c, 0x2a0b2, 0x2a0b4, - 0x2a312, 0x2a318, 0x2a382, 0x2a3c8, 0x2a3fe, 0x2a400, - 0x2a49a, 0x2a4b8, 0x2a51e, 0x2a548, 0x2a54e, 0x2a550, - 0x2a602, 0x2a60c, 0x2a6ce, 0x2a6d0, 0x2a6da, 0x2a6e8, - 0x2a6f2, 0x2a6f8, 0x2a702, 0x2a704, 0x2a796, 0x2a798, - 0x2a8a6, 0x2a8bc, 0x2a8c6, 0x2a8cc, 0x2a8d6, 0x2a8dc, - 0x2a90e, 0x2a910, 0x2a932, 0x2a934, 0x2a9f2, 0x2a9f4, - 0x2aac2, 0x2aac4, 0x2aaca, 0x2aad4, 0x2aade, 0x2aae4, - 0x2aafa, 0x2ab00, 0x2ab06, 0x2ab08, 0x2abb2, 0x2abb8, - 0x2abda, 0x2abdc, 0x2af96, 0x2af98, 0x2afa2, 0x2afa4, - 0x2afb6, 0x2afb8, 0x3ec7a, 0x3ec7c, 0x3f802, 0x3f840, - 0x3f882, 0x3f8c0, 0x3fe7a, 0x3fe80, 0x407f6, 0x407f8, - 0x40b82, 0x40b84, 0x40dda, 0x40dec, 0x42806, 0x42810, - 0x42816, 0x4281c, 0x42832, 0x42840, 0x428e2, 0x428ec, - 0x428fe, 0x42900, 0x42b96, 0x42b9c, 0x43492, 0x434a0, - 0x435a6, 0x435b8, 0x43aae, 0x43ab4, 0x43bf2, 0x43c00, - 0x43d1a, 0x43d44, 0x43e0a, 0x43e18, 0x44006, 0x44008, - 0x440e2, 0x4411c, 0x441c2, 0x441c4, 0x441ce, 0x441d4, - 0x441fe, 0x44208, 0x442ce, 0x442dc, 0x442e6, 0x442ec, - 0x4430a, 0x4430c, 0x44402, 0x4440c, 0x4449e, 0x444b0, - 0x444b6, 0x444d4, 0x445ce, 0x445d0, 0x44602, 0x44608, - 0x446da, 0x446fc, 0x44702, 0x44704, 0x44726, 0x44734, - 0x4473e, 0x44740, 0x448be, 0x448c8, 0x448d2, 0x448e0, - 0x448fa, 0x448fc, 0x44906, 0x44908, 0x44b7e, 0x44b80, - 0x44b8e, 0x44bac, 0x44c02, 0x44c08, 0x44cee, 0x44cf4, - 0x44cfa, 0x44cfc, 0x44d02, 0x44d04, 0x44d36, 0x44d38, - 0x44d5e, 0x44d60, 0x44d9a, 0x44db4, 0x44dc2, 0x44dd4, - 0x44ee2, 0x44ee4, 0x44eee, 0x44f04, 0x44f0a, 0x44f0c, - 0x44f16, 0x44f18, 0x44f1e, 0x44f28, 0x44f3a, 0x44f44, - 0x44f4a, 0x44f4c, 0x44f86, 0x44f8c, 0x450e2, 0x45100, - 0x4510a, 0x45114, 0x4511a, 0x4511c, 0x4517a, 0x4517c, - 0x452c2, 0x452c4, 0x452ce, 0x452e4, 0x452ea, 0x452ec, - 0x452f6, 0x452f8, 0x452fe, 0x45304, 0x4530a, 0x45310, - 0x456be, 0x456c0, 0x456ca, 0x456d8, 0x456f2, 0x456f8, - 0x456fe, 0x45704, 0x45772, 0x45778, 0x458ce, 0x458ec, - 0x458f6, 0x458f8, 0x458fe, 0x45904, 0x45aae, 0x45ab0, - 0x45ab6, 0x45ab8, 0x45ac2, 0x45ae0, 0x45c76, 0x45c78, - 0x45c7e, 0x45c80, 0x45c8a, 0x45c98, 0x45c9e, 0x45cb0, - 0x460be, 0x460e0, 0x460e6, 0x460ec, 0x464c2, 0x464c4, - 0x464ee, 0x464fc, 0x4650e, 0x46510, 0x46752, 0x46760, - 0x4676a, 0x46770, 0x46782, 0x46784, 0x46806, 0x4682c, - 0x468ce, 0x468e4, 0x468ee, 0x468fc, 0x4691e, 0x46920, - 0x46946, 0x4695c, 0x46966, 0x46970, 0x46a2a, 0x46a5c, - 0x46a62, 0x46a68, 0x470c2, 0x470dc, 0x470e2, 0x470f8, - 0x470fe, 0x47100, 0x4724a, 0x472a0, 0x472aa, 0x472c4, - 0x472ca, 0x472d0, 0x472d6, 0x472dc, 0x474c6, 0x474dc, - 0x474ea, 0x474ec, 0x474f2, 0x474f8, 0x474fe, 0x47518, - 0x4751e, 0x47520, 0x47642, 0x47648, 0x47656, 0x47658, - 0x4765e, 0x47660, 0x47bce, 0x47bd4, 0x47c02, 0x47c08, - 0x47cda, 0x47cec, 0x47d02, 0x47d0c, 0x47d6a, 0x47d6c, - 0x4d102, 0x4d104, 0x4d11e, 0x4d158, 0x5847a, 0x584a8, - 0x584b6, 0x584c0, 0x5abc2, 0x5abd4, 0x5acc2, 0x5acdc, - 0x5bd3e, 0x5bd40, 0x5be3e, 0x5be4c, 0x5bf92, 0x5bf94, - 0x5bfc2, 0x5bfc8, 0x6f276, 0x6f27c, 0x73c02, 0x73cb8, - 0x73cc2, 0x73d1c, 0x74596, 0x745a8, 0x745b6, 0x745cc, - 0x745ee, 0x7460c, 0x74616, 0x74630, 0x746aa, 0x746b8, - 0x7490a, 0x74914, 0x76802, 0x768dc, 0x768ee, 0x769b4, - 0x769d6, 0x769d8, 0x76a12, 0x76a14, 0x76a6e, 0x76a80, - 0x76a86, 0x76ac0, 0x78002, 0x7801c, 0x78022, 0x78064, - 0x7806e, 0x78088, 0x7808e, 0x78094, 0x7809a, 0x780ac, - 0x7823e, 0x78240, 0x784c2, 0x784dc, 0x78aba, 0x78abc, - 0x78bb2, 0x78bc0, 0x793b2, 0x793c0, 0x797ba, 0x797c0, - 0x7a342, 0x7a35c, 0x7a512, 0x7a52c, 0x7cfee, 0x7d000, - 0x380082, 0x380200, 0x380402, 0x3807c0, + 0x4001, 0x40ac, 0x40b6, 0x40c4, 0x40ca, 0x40e0, + 0x40ea, 0x40ec, 0x40f6, 0x40fd, 0x4100, 0x4141, + 0x4158, 0x4162, 0x4169, 0x417a, 0x4185, 0x4188, + 0x4195, 0x419c, 0x41b9, 0x41c6, 0x41d5, 0x420a, + 0x420c, 0x4216, 0x421c, 0x4236, 0x4239, 0x423c, + 0x4276, 0x4278, 0x4d76, 0x4d80, 0x5c4a, 0x5c58, + 0x5cca, 0x5cd4, 0x5d4a, 0x5d50, 0x5dca, 0x5dd0, + 0x5e01, 0x5ed2, 0x5ed8, 0x5ede, 0x5ef8, 0x5f1a, + 0x5f1c, 0x5f26, 0x5f48, 0x5f4e, 0x5f50, 0x5f76, + 0x5f78, 0x602e, 0x6038, 0x603e, 0x6040, 0x6216, + 0x621c, 0x62a6, 0x62a8, 0x6482, 0x648c, 0x649e, + 0x64a4, 0x64ca, 0x64cc, 0x64e6, 0x64f0, 0x685e, + 0x6864, 0x686e, 0x6870, 0x6881, 0x6954, 0x695a, + 0x695c, 0x6962, 0x697c, 0x698a, 0x698c, 0x6996, + 0x69b4, 0x69ce, 0x69f4, 0x69fe, 0x6a00, 0x6ac2, + 0x6b78, 0x6b82, 0x6bb0, 0x6c02, 0x6c10, 0x6c2d, + 0x6c34, 0x6c4d, 0x6cd2, 0x6cf8, 0x6d0a, 0x6d10, + 0x6d15, 0x6d34, 0x6dae, 0x6dd0, 0x6e02, 0x6e08, + 0x6e0d, 0x6e84, 0x6e8a, 0x6e98, 0x6ea2, 0x6eac, + 0x6eb2, 0x6eb9, 0x6ec0, 0x6eed, 0x6ef8, 0x6f9a, + 0x6f9c, 0x6fa2, 0x6fa8, 0x6fb6, 0x6fb8, 0x6fbe, + 0x6fd0, 0x70b2, 0x70d0, 0x70da, 0x70e0, 0x7342, + 0x734c, 0x7352, 0x7384, 0x738a, 0x73a4, 0x73b6, + 0x73b8, 0x73d2, 0x73d4, 0x73e2, 0x73e8, 0x7702, + 0x7800, 0x8036, 0x8038, 0x8342, 0x83c4, 0xb3be, + 0xb3c8, 0xb5fe, 0xb600, 0xb782, 0xb800, 0xc0aa, + 0xc0c0, 0xc266, 0xc26c, 0x299be, 0x299cc, 0x299d2, + 0x299f8, 0x29a7a, 0x29a80, 0x29bc2, 0x29bc8, 0x2a00a, + 0x2a00c, 0x2a01a, 0x2a01c, 0x2a02e, 0x2a030, 0x2a096, + 0x2a09c, 0x2a0b2, 0x2a0b4, 0x2a312, 0x2a318, 0x2a382, + 0x2a3c8, 0x2a3fe, 0x2a400, 0x2a49a, 0x2a4b8, 0x2a51e, + 0x2a548, 0x2a54e, 0x2a550, 0x2a602, 0x2a60c, 0x2a625, + 0x2a630, 0x2a63d, 0x2a6ce, 0x2a6d0, 0x2a6da, 0x2a6e8, + 0x2a6f2, 0x2a6f8, 0x2a781, 0x2a796, 0x2a798, 0x2a79d, + 0x2a7c0, 0x2a7e9, 0x2a7fc, 0x2a8a6, 0x2a8bc, 0x2a8c6, + 0x2a8cc, 0x2a8d6, 0x2a8dc, 0x2a90e, 0x2a910, 0x2a932, + 0x2a934, 0x2a981, 0x2a9c0, 0x2a9c5, 0x2a9d0, 0x2a9e9, + 0x2a9ec, 0x2a9f2, 0x2a9f4, 0x2a9f9, 0x2aa00, 0x2aac2, + 0x2aac4, 0x2aaca, 0x2aad4, 0x2aade, 0x2aae4, 0x2aafa, + 0x2ab00, 0x2ab06, 0x2ab08, 0x2ab81, 0x2abac, 0x2abb2, + 0x2abb8, 0x2af01, 0x2af6c, 0x2af96, 0x2af98, 0x2afa2, + 0x2afa4, 0x2afb6, 0x2afb8, 0x3ec7a, 0x3ec7c, 0x3f802, + 0x3f840, 0x3f882, 0x3f8c0, 0x3fe7a, 0x3fe80, 0x407f6, + 0x407f8, 0x40b82, 0x40b84, 0x40dda, 0x40dec, 0x42801, + 0x42806, 0x42810, 0x42816, 0x4281c, 0x42832, 0x42841, + 0x42850, 0x42855, 0x42860, 0x42865, 0x428d8, 0x428e2, + 0x428ec, 0x42b96, 0x42b9c, 0x43492, 0x434a0, 0x435a6, + 0x435b8, 0x43aae, 0x43ab4, 0x43bea, 0x43c00, 0x43d1a, + 0x43d44, 0x43e0a, 0x43e18, 0x44006, 0x44008, 0x440e2, + 0x4411c, 0x441c2, 0x441c4, 0x441ce, 0x441d4, 0x441fe, + 0x44208, 0x442ce, 0x442dc, 0x442e6, 0x442ec, 0x4430a, + 0x4430c, 0x44402, 0x4440d, 0x4449e, 0x444b0, 0x444b6, + 0x444cc, 0x444d2, 0x444d4, 0x44511, 0x44514, 0x4451d, + 0x44520, 0x445ce, 0x445d0, 0x44602, 0x44608, 0x446da, + 0x446fc, 0x44702, 0x44704, 0x44726, 0x44734, 0x4473e, + 0x44740, 0x448be, 0x448c8, 0x448d2, 0x448e0, 0x448fa, + 0x448fc, 0x44906, 0x44908, 0x44b7e, 0x44b80, 0x44b8e, + 0x44bac, 0x44c02, 0x44c08, 0x44cee, 0x44cf4, 0x44cfa, + 0x44cfc, 0x44d02, 0x44d04, 0x44d36, 0x44d38, 0x44d5e, + 0x44d60, 0x44d9a, 0x44db4, 0x44dc2, 0x44dd4, 0x44e01, + 0x44e28, 0x44e2d, 0x44e30, 0x44e39, 0x44e3c, 0x44e41, + 0x44ed8, 0x44ee2, 0x44ee4, 0x44eee, 0x44f04, 0x44f0a, + 0x44f0c, 0x44f16, 0x44f18, 0x44f1e, 0x44f28, 0x44f3a, + 0x44f40, 0x44f4a, 0x44f4c, 0x44f86, 0x44f8c, 0x450e2, + 0x45100, 0x4510a, 0x45114, 0x4511a, 0x4511c, 0x4517a, + 0x4517c, 0x452c2, 0x452c4, 0x452ce, 0x452e4, 0x452ea, + 0x452ec, 0x452f6, 0x452f8, 0x452fe, 0x45304, 0x4530a, + 0x45310, 0x456be, 0x456c0, 0x456ca, 0x456d8, 0x456f2, + 0x456f8, 0x456fe, 0x45704, 0x45772, 0x45778, 0x458ce, + 0x458ec, 0x458f6, 0x458f8, 0x458fe, 0x45904, 0x45aae, + 0x45ab0, 0x45ab6, 0x45ab8, 0x45ac2, 0x45ae0, 0x45c76, + 0x45c78, 0x45c7e, 0x45c80, 0x45c8a, 0x45c98, 0x45c9e, + 0x45cb0, 0x460be, 0x460e0, 0x460e6, 0x460ec, 0x46401, + 0x4641c, 0x46425, 0x46428, 0x46431, 0x46450, 0x46455, + 0x4645c, 0x46461, 0x464c2, 0x464c4, 0x464ee, 0x464f8, + 0x4650e, 0x46510, 0x46752, 0x46760, 0x4676a, 0x46770, + 0x46782, 0x46784, 0x46801, 0x46806, 0x4682d, 0x468ce, + 0x468e4, 0x468ee, 0x468fc, 0x46941, 0x46946, 0x4695c, + 0x46966, 0x46971, 0x46a10, 0x46a2a, 0x46a5c, 0x46a62, + 0x46a64, 0x46d82, 0x46d84, 0x46d8a, 0x46d94, 0x46d9a, + 0x46d9c, 0x470c2, 0x470dc, 0x470e2, 0x470f8, 0x470fe, + 0x47100, 0x4724a, 0x472a0, 0x472aa, 0x472c4, 0x472ca, + 0x472d0, 0x472d6, 0x472dc, 0x474c6, 0x474dc, 0x474ea, + 0x474ec, 0x474f2, 0x474f8, 0x474fe, 0x47518, 0x4751e, + 0x47520, 0x47642, 0x47648, 0x47656, 0x47658, 0x4765e, + 0x47660, 0x47bce, 0x47bd4, 0x47c02, 0x47c08, 0x47c11, + 0x47c44, 0x47c49, 0x47cd0, 0x47cda, 0x47cec, 0x47d02, + 0x47d08, 0x47d6a, 0x47d6c, 0x4d102, 0x4d104, 0x4d11e, + 0x4d158, 0x5847a, 0x584a8, 0x584b6, 0x584c0, 0x5abc2, + 0x5abd4, 0x5acc2, 0x5acdc, 0x5bd3e, 0x5bd40, 0x5be3e, + 0x5be4c, 0x5bf92, 0x5bf94, 0x5bfc2, 0x5bfc8, 0x6f276, + 0x6f27c, 0x73c02, 0x73cb8, 0x73cc2, 0x73d1c, 0x74596, + 0x745a8, 0x745b6, 0x745cc, 0x745ee, 0x7460c, 0x74616, + 0x74630, 0x746aa, 0x746b8, 0x7490a, 0x74914, 0x76802, + 0x768dc, 0x768ee, 0x769b4, 0x769d6, 0x769d8, 0x76a12, + 0x76a14, 0x76a6e, 0x76a80, 0x76a86, 0x76ac0, 0x78002, + 0x7801c, 0x78022, 0x78064, 0x7806e, 0x78088, 0x7808e, + 0x78094, 0x7809a, 0x780ac, 0x7823e, 0x78240, 0x784c2, + 0x784dc, 0x78aba, 0x78abc, 0x78bb2, 0x78bc0, 0x793b2, + 0x793c0, 0x797ba, 0x797c0, 0x79b8e, 0x79b90, 0x79b9a, + 0x79b9c, 0x79bba, 0x79bc0, 0x79bd6, 0x79bd8, 0x7a342, + 0x7a35c, 0x7a512, 0x7a52c, 0x7cfee, 0x7d000, 0x380082, + 0x380200, 0x380402, 0x3807c0, }; // Table generated by contrib/unicode/gen_libstdcxx_unicode_data.py, @@ -776,24 +795,43 @@ inline constexpr char32_t __xpicto_edges[] = { 0xa9, 0xaa, 0xae, 0xaf, 0x203c, 0x203d, 0x2049, 0x204a, 0x2122, 0x2123, 0x2139, 0x213a, 0x2194, 0x219a, 0x21a9, 0x21ab, - 0x231a, 0x231c, 0x2328, 0x2329, 0x2388, 0x2389, 0x23cf, 0x23d0, - 0x23e9, 0x23f4, 0x23f8, 0x23fb, 0x24c2, 0x24c3, 0x25aa, 0x25ac, - 0x25b6, 0x25b7, 0x25c0, 0x25c1, 0x25fb, 0x25ff, 0x2600, 0x2606, - 0x2607, 0x2613, 0x2614, 0x2686, 0x2690, 0x2706, 0x2708, 0x2713, - 0x2714, 0x2715, 0x2716, 0x2717, 0x271d, 0x271e, 0x2721, 0x2722, - 0x2728, 0x2729, 0x2733, 0x2735, 0x2744, 0x2745, 0x2747, 0x2748, - 0x274c, 0x274d, 0x274e, 0x274f, 0x2753, 0x2756, 0x2757, 0x2758, - 0x2763, 0x2768, 0x2795, 0x2798, 0x27a1, 0x27a2, 0x27b0, 0x27b1, - 0x27bf, 0x27c0, 0x2934, 0x2936, 0x2b05, 0x2b08, 0x2b1b, 0x2b1d, - 0x2b50, 0x2b51, 0x2b55, 0x2b56, 0x3030, 0x3031, 0x303d, 0x303e, - 0x3297, 0x3298, 0x3299, 0x329a, 0x1f000, 0x1f100, 0x1f10d, 0x1f110, - 0x1f12f, 0x1f130, 0x1f16c, 0x1f172, 0x1f17e, 0x1f180, 0x1f18e, 0x1f18f, - 0x1f191, 0x1f19b, 0x1f1ad, 0x1f1e6, 0x1f201, 0x1f210, 0x1f21a, 0x1f21b, - 0x1f22f, 0x1f230, 0x1f232, 0x1f23b, 0x1f23c, 0x1f240, 0x1f249, 0x1f3fb, - 0x1f400, 0x1f53e, 0x1f546, 0x1f650, 0x1f680, 0x1f700, 0x1f774, 0x1f780, - 0x1f7d5, 0x1f800, 0x1f80c, 0x1f810, 0x1f848, 0x1f850, 0x1f85a, 0x1f860, - 0x1f888, 0x1f890, 0x1f8ae, 0x1f900, 0x1f90c, 0x1f93b, 0x1f93c, 0x1f946, - 0x1f947, 0x1fb00, 0x1fc00, 0x1fffe, + 0x231a, 0x231c, 0x2328, 0x2329, 0x23cf, 0x23d0, 0x23e9, 0x23f4, + 0x23f8, 0x23fb, 0x24c2, 0x24c3, 0x25aa, 0x25ac, 0x25b6, 0x25b7, + 0x25c0, 0x25c1, 0x25fb, 0x25ff, 0x2600, 0x2605, 0x260e, 0x260f, + 0x2611, 0x2612, 0x2614, 0x2616, 0x2618, 0x2619, 0x261d, 0x261e, + 0x2620, 0x2621, 0x2622, 0x2624, 0x2626, 0x2627, 0x262a, 0x262b, + 0x262e, 0x2630, 0x2638, 0x263b, 0x2640, 0x2641, 0x2642, 0x2643, + 0x2648, 0x2654, 0x265f, 0x2661, 0x2663, 0x2664, 0x2665, 0x2667, + 0x2668, 0x2669, 0x267b, 0x267c, 0x267e, 0x2680, 0x2692, 0x2698, + 0x2699, 0x269a, 0x269b, 0x269d, 0x26a0, 0x26a2, 0x26a7, 0x26a8, + 0x26aa, 0x26ac, 0x26b0, 0x26b2, 0x26bd, 0x26bf, 0x26c4, 0x26c6, + 0x26c8, 0x26c9, 0x26ce, 0x26d0, 0x26d1, 0x26d2, 0x26d3, 0x26d5, + 0x26e9, 0x26eb, 0x26f0, 0x26f6, 0x26f7, 0x26fb, 0x26fd, 0x26fe, + 0x2702, 0x2703, 0x2705, 0x2706, 0x2708, 0x270e, 0x270f, 0x2710, + 0x2712, 0x2713, 0x2714, 0x2715, 0x2716, 0x2717, 0x271d, 0x271e, + 0x2721, 0x2722, 0x2728, 0x2729, 0x2733, 0x2735, 0x2744, 0x2745, + 0x2747, 0x2748, 0x274c, 0x274d, 0x274e, 0x274f, 0x2753, 0x2756, + 0x2757, 0x2758, 0x2763, 0x2765, 0x2795, 0x2798, 0x27a1, 0x27a2, + 0x27b0, 0x27b1, 0x27bf, 0x27c0, 0x2934, 0x2936, 0x2b05, 0x2b08, + 0x2b1b, 0x2b1d, 0x2b50, 0x2b51, 0x2b55, 0x2b56, 0x3030, 0x3031, + 0x303d, 0x303e, 0x3297, 0x3298, 0x3299, 0x329a, 0x1f004, 0x1f005, + 0x1f02c, 0x1f030, 0x1f094, 0x1f0a0, 0x1f0af, 0x1f0b1, 0x1f0c0, 0x1f0c1, + 0x1f0cf, 0x1f0d1, 0x1f0f6, 0x1f100, 0x1f170, 0x1f172, 0x1f17e, 0x1f180, + 0x1f18e, 0x1f18f, 0x1f191, 0x1f19b, 0x1f1ae, 0x1f1e6, 0x1f201, 0x1f210, + 0x1f21a, 0x1f21b, 0x1f22f, 0x1f230, 0x1f232, 0x1f23b, 0x1f23c, 0x1f240, + 0x1f249, 0x1f260, 0x1f266, 0x1f322, 0x1f324, 0x1f394, 0x1f396, 0x1f398, + 0x1f399, 0x1f39c, 0x1f39e, 0x1f3f1, 0x1f3f3, 0x1f3f6, 0x1f3f7, 0x1f3fb, + 0x1f400, 0x1f4fe, 0x1f4ff, 0x1f53e, 0x1f549, 0x1f54f, 0x1f550, 0x1f568, + 0x1f56f, 0x1f571, 0x1f573, 0x1f57b, 0x1f587, 0x1f588, 0x1f58a, 0x1f58e, + 0x1f590, 0x1f591, 0x1f595, 0x1f597, 0x1f5a4, 0x1f5a6, 0x1f5a8, 0x1f5a9, + 0x1f5b1, 0x1f5b3, 0x1f5bc, 0x1f5bd, 0x1f5c2, 0x1f5c5, 0x1f5d1, 0x1f5d4, + 0x1f5dc, 0x1f5df, 0x1f5e1, 0x1f5e2, 0x1f5e3, 0x1f5e4, 0x1f5e8, 0x1f5e9, + 0x1f5ef, 0x1f5f0, 0x1f5f3, 0x1f5f4, 0x1f5fa, 0x1f650, 0x1f680, 0x1f6c6, + 0x1f6cb, 0x1f6d3, 0x1f6d5, 0x1f6e6, 0x1f6e9, 0x1f6ea, 0x1f6eb, 0x1f6f1, + 0x1f6f3, 0x1f700, 0x1f7da, 0x1f800, 0x1f80c, 0x1f810, 0x1f848, 0x1f850, + 0x1f85a, 0x1f860, 0x1f888, 0x1f890, 0x1f8ae, 0x1f8b0, 0x1f8bc, 0x1f8c0, + 0x1f8c2, 0x1f8d0, 0x1f8d9, 0x1f900, 0x1f90c, 0x1f93b, 0x1f93c, 0x1f946, + 0x1f947, 0x1fa00, 0x1fa58, 0x1fa60, 0x1fa6e, 0x1fb00, 0x1fc00, 0x1fffe, }; #undef _GLIBCXX_GET_UNICODE_DATA diff --git a/libstdc++-v3/include/bits/unicode.h b/libstdc++-v3/include/bits/unicode.h index f1b6bf4..09f7c2d 100644 --- a/libstdc++-v3/include/bits/unicode.h +++ b/libstdc++-v3/include/bits/unicode.h @@ -61,7 +61,7 @@ namespace __unicode __is_single_code_unit(char32_t __c) { if constexpr (__gnu_cxx::__int_traits<_CharT>::__max <= 0xFF) - return __c < 0x7F; // ASCII character + return __c <= 0x7F; // ASCII character else return __c < __gnu_cxx::__int_traits<_CharT>::__max && __is_scalar_value(__c); @@ -86,6 +86,25 @@ namespace __unicode { return *__it == iter_value_t<_It>{}; } }; + // An iterator over an input range of FromFmt code units that yields either + // UTF-8, UTF-16, or UTF-32, as a range of ToFmt code units. + // The code units from the input range are interpreted as Unicode code points + // and the iterator produces the individual code unit for each code point. + // Invalid sequences in the input are replaced with U+FFDD so that the result + // is always valid UTF-8, UTF-16, or UTF-32. + // + // The iterator knows the bounds of the underlying input range and will not + // read outside those bounds (incrementing or decrementing at the boundary + // is erroneously idempotent). + // + // On construction, the iterator attemps to decode a single code point from + // the input range and then encode it into an internal buffer in the output + // format, e.g. if the input is UTF-8 and the output is UTF-16, it might read + // three char8_t code units from the input and store two char16_t code units + // in its buffer. Incrementing the iterator will first iterate over buffer, + // yielding each code unit in turn, and then extract another code point from + // the input. Failure to extract a valid code point from the input will store + // U+FFFD in the buffer, encoded as the appropriate code units of type ToFmt. template<typename _FromFmt, typename _ToFmt, input_iterator _Iter, sentinel_for<_Iter> _Sent = _Iter, typename _ErrorHandler = _Repl> @@ -162,17 +181,20 @@ namespace __unicode constexpr _Utf_iterator& operator++() { - if (_M_buf_index + 1 == _M_buf_last && _M_curr() != _M_last) + if (_M_buf_index + 1 < _M_buf_last) + ++_M_buf_index; // Move to the next code unit in the buffer. + else if (_M_curr() != _M_last) { + // Advance past the current code point (for non-forward iterators + // we already moved there after decoding the last code point). if constexpr (forward_iterator<_Iter>) std::advance(_M_curr(), _M_to_increment); if (_M_curr() == _M_last) _M_buf_index = 0; - else + else // Decode next code point from the input and update buffer. _M_read(); } - else if (_M_buf_index + 1 < _M_buf_last) - ++_M_buf_index; + // else erroneous, but ignored for now. return *this; } @@ -187,10 +209,15 @@ namespace __unicode constexpr _Utf_iterator& operator--() requires bidirectional_iterator<_Iter> { - if (!_M_buf_index && _M_curr() != _M_first()) - _M_read_reverse(); - else if (_M_buf_index) + if (_M_buf_index > 0) --_M_buf_index; + else if (_M_curr() != _M_first()) + { + _M_read_reverse(); + _M_buf_index = _M_buf_last - 1; + ranges::advance(_M_curr(), -_M_to_increment); + } + // else erroneous, but ignored for now. return *this; } @@ -247,7 +274,18 @@ namespace __unicode } constexpr void - _M_read_reverse(); // TODO + _M_read_reverse() requires bidirectional_iterator<_Iter> + { + if constexpr (sizeof(_FromFmt) == sizeof(uint8_t)) + _M_read_reverse_utf8(); + else if constexpr (sizeof(_FromFmt) == sizeof(uint16_t)) + _M_read_reverse_utf16(); + else + { + static_assert(sizeof(_FromFmt) == sizeof(uint32_t)); + _M_read_reverse_utf32(); + } + } template<typename> struct _Guard @@ -263,7 +301,7 @@ namespace __unicode _It _M_orig; }; - constexpr void + constexpr char32_t _M_read_utf8() { _Guard<_Iter> __g{this, _M_curr()}; @@ -361,6 +399,8 @@ namespace __unicode __c = _S_error(); _M_update(__c, __to_incr); + + return __c; } constexpr void @@ -403,6 +443,116 @@ namespace __unicode _M_update(__c, 1); } + constexpr void + _M_read_reverse_utf8() requires bidirectional_iterator<_Iter> + { + const auto __first = _M_first(); + auto __curr = _M_curr(); + // The code point we decode: + char32_t __c{}; + // The last code unit read: + uint8_t __u = *--__curr; + // Count of bytes read: + uint8_t __to_incr = 1; + + if (__u <= 0x7F) [[likely]] + { + _M_update(__u, 1); + return; + } + + // Continuation bytes match 10xxxxxx + auto __is_continuation = [](uint8_t __b) { + return (__b & 0xC0) == 0x80; + }; + // 0xC0 and 0xC1 would produce overlong encodings of ASCII characters. + // 0xF5-0xFF would produce code points above U+10FFFF + auto __is_invalid = [](uint8_t __b) { + return (__b & 0xFE) == 0xC0 || __b >= 0xF5; + }; + + // No valid or invalid multibyte sequence is longer than 4 bytes, + // so skip back over at most four bytes. + while (__is_continuation(__u) && __to_incr < 4 && __curr != __first) + { + ++__to_incr; + __u = *--__curr; + } + + // If the last byte read was a continuation byte then either we read + // four continuation bytes, or stopped at the start of the sequence. + // Either way, the maximal subparts are the individual continuation + // bytes so each one should be replaced with U+FFFD. + if (__is_continuation(__u) || __is_invalid(__u)) [[unlikely]] + { + // Either found four continuation bytes (maximum allowed is three) + // or first non-continuation byte is an invalid UTF-8 code unit. + _M_update(_S_error(), 1); + return; + } + // __u is a valid start byte so use countl_one to get the expected + // length of the multibyte sequence that starts with this byte. + int __seq_length = std::countl_one((unsigned char)__u); + if (__seq_length < __to_incr) [[unlikely]] + { + // If the expected number of continuation bytes is less than + // the number we found, then the last continuation byte is a + // maximal subpart and the decremented iterator points to it. + _M_update(_S_error(), 1); + return; + } + + auto __orig = std::__exchange(_M_curr(), std::move(__curr)); + if (_M_read_utf8() == _S_error()) [[unlikely]] + { + if (_M_to_increment < __to_incr) // Read truncated sequence, set + _M_to_increment = 1; // curr to last continuation byte. + } + + _M_curr() = std::move(__orig); + // operator--() will move back by _M_to_increment + } + + constexpr void + _M_read_reverse_utf16() requires bidirectional_iterator<_Iter> + { + _Guard<_Iter> __g{this, _M_curr()}; + char32_t __c{}; + uint16_t __u = *--_M_curr(); + uint8_t __to_incr = 1; + + if (__u < 0xD800 || __u > 0xDFFF) [[likely]] + __c = __u; + else if (__u >= 0xDC00 && _M_curr() != _M_first()) [[likely]] + { + // read a low surrogate, expect a high surrogate before it. + uint16_t __u2 = *--_M_curr(); + if (__u2 < 0xD800 || __u2 >= 0xDC00) [[unlikely]] + __c = _S_error(); // unpaired low surrogate + else + { + __to_incr = 2; + uint32_t __x = (__u2 & 0x3F) << 10 | (__u & 0x3FF); + uint32_t __w = (__u2 >> 6) & 0x1F; + __c = (__w + 1) << 16 | __x; + } + } + else + __c = _S_error(); // unpaired surrogate + + _M_update(__c, __to_incr); + } + + constexpr void + _M_read_reverse_utf32() requires bidirectional_iterator<_Iter> + { + _Guard<_Iter> __g{this, _M_curr()}; + char32_t __c = *--_M_curr(); + if (!__is_scalar_value(__c)) [[unlikely]] + __c = _S_error(); + _M_update(__c, 1); + } + // Encode the code point __c as one or more code units in _M_buf. constexpr void _M_update(char32_t __c, uint8_t __to_incr) @@ -487,8 +637,7 @@ namespace __unicode constexpr _Iter _M_curr() const { return _M_first_and_curr._M_curr; } - array<value_type, 4 / sizeof(_ToFmt)> _M_buf; - + // _M_first is not needed for non-bidirectional ranges. template<typename _It> struct _First_and_curr { @@ -502,6 +651,8 @@ namespace __unicode _First_and_curr(const _First_and_curr<_It2>& __other) : _M_curr(__other._M_curr) { } + // First code unit of the current code point for forward iterators, + // past-the-end of the current code point for input iterators. _It _M_curr; }; @@ -519,18 +670,24 @@ namespace __unicode _First_and_curr(const _First_and_curr<_It2>& __other) : _M_first(__other._M_first), _M_curr(__other._M_curr) { } - _It _M_first; - _It _M_curr; + _It _M_first; // Start of the underlying range. + _It _M_curr; // First code unit of the current code point. }; + // Iterators pointing to the start of the underlying range and to the + // start (or end, for non-forward iterators) of the current code point. _First_and_curr<_Iter> _M_first_and_curr; - uint8_t _M_buf_index = 0; - uint8_t _M_buf_last = 0; - uint8_t _M_to_increment = 0; - + // The end of the underlying input range. [[no_unique_address]] _Sent _M_last; + // Buffer holding the individual code units of the current code point. + array<value_type, 4 / sizeof(_ToFmt)> _M_buf; + + uint8_t _M_buf_index = 0; // Index of current code unit in the buffer. + uint8_t _M_buf_last = 0; // Number of code units in the buffer. + uint8_t _M_to_increment = 0; // How far to advance _M_curr on increment. + template<typename _FromFmt2, typename _ToFmt2, input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, typename _ErrHandler> @@ -538,13 +695,14 @@ namespace __unicode friend class _Utf_iterator; }; - template<typename _ToFormat, ranges::input_range _Range> + template<typename _ToFormat, ranges::input_range _View> + requires ranges::view<_View> class _Utf_view - : public ranges::view_interface<_Utf_view<_ToFormat, _Range>> + : public ranges::view_interface<_Utf_view<_ToFormat, _View>> { - using _Iterator = _Utf_iterator<ranges::range_value_t<_Range>, - _ToFormat, ranges::iterator_t<_Range>, - ranges::sentinel_t<_Range>>; + using _Iterator = _Utf_iterator<ranges::range_value_t<_View>, + _ToFormat, ranges::iterator_t<_View>, + ranges::sentinel_t<_View>>; template<typename _Iter, typename _Sent> constexpr auto @@ -568,11 +726,11 @@ namespace __unicode return _Iterator(__last, __last); } - _Range _M_base; + _View _M_base; public: constexpr explicit - _Utf_view(_Range&& __r) : _M_base(std::forward<_Range>(__r)) { } + _Utf_view(_View __r) : _M_base(std::move(__r)) { } constexpr auto begin() { return _M_begin(ranges::begin(_M_base), ranges::end(_M_base)); } diff --git a/libstdc++-v3/include/bits/unique_ptr.h b/libstdc++-v3/include/bits/unique_ptr.h index 6ae46a9..978deb3 100644 --- a/libstdc++-v3/include/bits/unique_ptr.h +++ b/libstdc++-v3/include/bits/unique_ptr.h @@ -1,4 +1,3 @@ - // unique_ptr implementation -*- C++ -*- // Copyright (C) 2008-2025 Free Software Foundation, Inc. @@ -832,6 +831,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __x.swap(__y); } #if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2766. Swapping non-swappable types template<typename _Tp, typename _Dp> typename enable_if<!__is_swappable<_Dp>::value>::type swap(unique_ptr<_Tp, _Dp>&, diff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h index fc07ffc..b9b2772 100644 --- a/libstdc++-v3/include/bits/unordered_map.h +++ b/libstdc++-v3/include/bits/unordered_map.h @@ -91,9 +91,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * @tparam _Key Type of key objects. * @tparam _Tp Type of mapped objects. - * @tparam _Hash Hashing function object type, defaults to hash<_Value>. + * @tparam _Hash Hashing function object type, defaults to hash<_Key>. * @tparam _Pred Predicate function object type, defaults - * to equal_to<_Value>. + * to equal_to<_Key>. * @tparam _Alloc Allocator type, defaults to * std::allocator<std::pair<const _Key, _Tp>>. * @@ -961,7 +961,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER find(const key_type& __x) { return _M_h.find(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto find(const _Kt& __x) -> decltype(_M_h._M_find_tr(__x)) @@ -972,7 +972,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER find(const key_type& __x) const { return _M_h.find(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto find(const _Kt& __x) const -> decltype(_M_h._M_find_tr(__x)) @@ -994,7 +994,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER count(const key_type& __x) const { return _M_h.count(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto count(const _Kt& __x) const -> decltype(_M_h._M_count_tr(__x)) @@ -1034,7 +1034,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER equal_range(const key_type& __x) { return _M_h.equal_range(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto equal_range(const _Kt& __x) @@ -1046,7 +1046,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER equal_range(const key_type& __x) const { return _M_h.equal_range(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto equal_range(const _Kt& __x) const @@ -1360,9 +1360,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * * @tparam _Key Type of key objects. * @tparam _Tp Type of mapped objects. - * @tparam _Hash Hashing function object type, defaults to hash<_Value>. + * @tparam _Hash Hashing function object type, defaults to hash<_Key>. * @tparam _Pred Predicate function object type, defaults - * to equal_to<_Value>. + * to equal_to<_Key>. * @tparam _Alloc Allocator type, defaults to * std::allocator<std::pair<const _Key, _Tp>>. * @@ -2039,7 +2039,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER find(const key_type& __x) { return _M_h.find(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto find(const _Kt& __x) -> decltype(_M_h._M_find_tr(__x)) @@ -2050,7 +2050,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER find(const key_type& __x) const { return _M_h.find(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto find(const _Kt& __x) const -> decltype(_M_h._M_find_tr(__x)) @@ -2068,7 +2068,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER count(const key_type& __x) const { return _M_h.count(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto count(const _Kt& __x) const -> decltype(_M_h._M_count_tr(__x)) @@ -2106,7 +2106,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER equal_range(const key_type& __x) { return _M_h.equal_range(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto equal_range(const _Kt& __x) @@ -2118,7 +2118,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER equal_range(const key_type& __x) const { return _M_h.equal_range(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto equal_range(const _Kt& __x) const diff --git a/libstdc++-v3/include/bits/unordered_set.h b/libstdc++-v3/include/bits/unordered_set.h index 5649dd7..29bc49a 100644 --- a/libstdc++-v3/include/bits/unordered_set.h +++ b/libstdc++-v3/include/bits/unordered_set.h @@ -744,7 +744,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER find(const key_type& __x) { return _M_h.find(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto find(const _Kt& __k) @@ -756,7 +756,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER find(const key_type& __x) const { return _M_h.find(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto find(const _Kt& __k) const @@ -779,7 +779,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER count(const key_type& __x) const { return _M_h.count(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto count(const _Kt& __k) const @@ -820,7 +820,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER equal_range(const key_type& __x) { return _M_h.equal_range(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto equal_range(const _Kt& __k) @@ -832,7 +832,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER equal_range(const key_type& __x) const { return _M_h.equal_range(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto equal_range(const _Kt& __k) const @@ -1745,7 +1745,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER find(const key_type& __x) { return _M_h.find(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto find(const _Kt& __x) @@ -1757,7 +1757,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER find(const key_type& __x) const { return _M_h.find(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto find(const _Kt& __x) const @@ -1776,7 +1776,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER count(const key_type& __x) const { return _M_h.count(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto count(const _Kt& __x) const -> decltype(_M_h._M_count_tr(__x)) @@ -1814,7 +1814,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER equal_range(const key_type& __x) { return _M_h.equal_range(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto equal_range(const _Kt& __x) @@ -1826,7 +1826,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER equal_range(const key_type& __x) const { return _M_h.equal_range(__x); } -#if __cplusplus > 201703L +#ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED template<typename _Kt> auto equal_range(const _Kt& __x) const diff --git a/libstdc++-v3/include/bits/utility.h b/libstdc++-v3/include/bits/utility.h index 6fa6b67..96ac698 100644 --- a/libstdc++-v3/include/bits/utility.h +++ b/libstdc++-v3/include/bits/utility.h @@ -137,26 +137,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using tuple_element_t = typename tuple_element<__i, _Tp>::type; #endif - // Stores a tuple of indices. Used by tuple and pair, and by bind() to - // extract the elements in a tuple. - template<size_t... _Indexes> struct _Index_tuple { }; - - // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. - template<size_t _Num> - struct _Build_index_tuple - { -#if __has_builtin(__make_integer_seq) - template<typename, size_t... _Indices> - using _IdxTuple = _Index_tuple<_Indices...>; - - // Clang defines __make_integer_seq for this purpose. - using __type = __make_integer_seq<_IdxTuple, size_t, _Num>; -#else - // For GCC and other compilers, use __integer_pack instead. - using __type = _Index_tuple<__integer_pack(_Num)...>; -#endif - }; - #ifdef __glibcxx_integer_sequence // C++ >= 14 /// Class template integer_sequence @@ -192,6 +172,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using index_sequence_for = make_index_sequence<sizeof...(_Types)>; #endif // __glibcxx_integer_sequence +#if __cpp_structured_bindings >= 202411L +#if __has_builtin(__integer_pack) + template <auto _Num, typename _Tp = decltype(_Num)> + inline constexpr _Tp + _IotaArray[_Num] = {__integer_pack(_Tp(_Num))...}; +#elif defined __glibcxx_integer_sequence + template <auto _Num, typename _Tp = decltype(_Num), typename = make_integer_sequence<_Tp, _Num>> + inline constexpr _Tp + _IotaArray[_Num]; + + template <auto _Num, typename _Tp, _Tp... _Is> + inline constexpr _Tp + _IotaArray<_Num, _Tp, integer_sequence<_Tp, _Is...>>[_Num] = {_Is...}; +#endif // __integer_pack +#endif // __cpp_structured_bindings >= 202411L + #if __cplusplus >= 201703L struct in_place_t { @@ -316,6 +312,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline constexpr sorted_equivalent_t sorted_equivalent{}; #endif +#if __glibcxx_function_ref // >= C++26 + template<auto> + struct nontype_t + { + explicit nontype_t() = default; + }; + + template<auto __val> + constexpr nontype_t<__val> nontype{}; + + template<typename> + inline constexpr bool __is_nontype_v = false; + + template<auto __val> + inline constexpr bool __is_nontype_v<nontype_t<__val>> = true; +#endif + _GLIBCXX_END_NAMESPACE_VERSION } // namespace diff --git a/libstdc++-v3/include/bits/valarray_array.h b/libstdc++-v3/include/bits/valarray_array.h index b5c02b7..d1b712c 100644 --- a/libstdc++-v3/include/bits/valarray_array.h +++ b/libstdc++-v3/include/bits/valarray_array.h @@ -38,6 +38,7 @@ #include <bits/c++config.h> #include <bits/cpp_type_traits.h> +#include <bits/new_allocator.h> #include <cstdlib> #include <new> @@ -57,12 +58,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> inline _Tp* __valarray_get_storage(size_t __n) - { return static_cast<_Tp*>(operator new(__n * sizeof(_Tp))); } + { return std::__new_allocator<_Tp>().allocate(__n); } // Return memory to the system - inline void - __valarray_release_memory(void* __p) - { operator delete(__p); } + template<typename _Tp> + inline void + __valarray_release_memory(_Tp* __p, size_t __n) + { std::__new_allocator<_Tp>().deallocate(__p, __n); } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc index e18f01a..642edb5 100644 --- a/libstdc++-v3/include/bits/vector.tcc +++ b/libstdc++-v3/include/bits/vector.tcc @@ -466,7 +466,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { const size_type __len = _M_check_len(1u, "vector::_M_realloc_insert"); if (__len <= 0) - __builtin_unreachable (); + __builtin_unreachable(); pointer __old_start = this->_M_impl._M_start; pointer __old_finish = this->_M_impl._M_finish; const size_type __elems_before = __position - begin(); @@ -573,10 +573,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { const size_type __len = _M_check_len(1u, "vector::_M_realloc_append"); if (__len <= 0) - __builtin_unreachable (); + __builtin_unreachable(); pointer __old_start = this->_M_impl._M_start; pointer __old_finish = this->_M_impl._M_finish; - const size_type __elems = end() - begin(); + const size_type __elems = size(); pointer __new_start(this->_M_allocate(__len)); pointer __new_finish(__new_start); @@ -664,8 +664,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { if (__n != 0) { - if (size_type(this->_M_impl._M_end_of_storage - - this->_M_impl._M_finish) >= __n) + if (__position.base() == this->_M_impl._M_finish) + _M_fill_append(__n, __x); + else if (size_type(this->_M_impl._M_end_of_storage + - this->_M_impl._M_finish) >= __n) { #if __cplusplus < 201103L value_type __x_copy = __x; @@ -760,6 +762,60 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } } + template<typename _Tp, typename _Alloc> + _GLIBCXX20_CONSTEXPR + void + vector<_Tp, _Alloc>:: + _M_fill_append(size_type __n, const value_type& __x) + { + if (size_type(this->_M_impl._M_end_of_storage + - this->_M_impl._M_finish) >= __n) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(__n); + this->_M_impl._M_finish = + std::__uninitialized_fill_n_a(this->_M_impl._M_finish, __n, __x, + _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_GREW(__n); + } + else + { + // Make local copies of these members because the compiler thinks + // the allocator can alter them if 'this' is globally reachable. + pointer __old_start = this->_M_impl._M_start; + pointer __old_finish = this->_M_impl._M_finish; + const size_type __old_size = __old_finish - __old_start; + + const size_type __len = + _M_check_len(__n, "vector::_M_fill_append"); + pointer __new_start(this->_M_allocate(__len)); + pointer __new_finish(__new_start + __old_size); + __try + { + // See _M_realloc_insert above. + __new_finish = std::__uninitialized_fill_n_a( + __new_finish, __n, __x, + _M_get_Tp_allocator()); + std::__uninitialized_move_if_noexcept_a( + __old_start, __old_finish, __new_start, + _M_get_Tp_allocator()); + } + __catch(...) + { + std::_Destroy(__new_start + __old_size, __new_finish, + _M_get_Tp_allocator()); + _M_deallocate(__new_start, __len); + __throw_exception_again; + } + std::_Destroy(__old_start, __old_finish, _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_REINIT; + _M_deallocate(__old_start, + this->_M_impl._M_end_of_storage - __old_start); + this->_M_impl._M_start = __new_start; + this->_M_impl._M_finish = __new_finish; + this->_M_impl._M_end_of_storage = __new_start + __len; + } + } + #if __cplusplus >= 201103L #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr @@ -1007,15 +1063,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER if constexpr (ranges::forward_range<_Rg>) { + const auto __ins_idx = __pos - cbegin(); + // Number of new elements to insert: + const auto __n = size_type(ranges::distance(__rg)); + if (__n == 0) + return begin() + __ins_idx; + // Start of existing elements: pointer __old_start = this->_M_impl._M_start; // End of existing elements: pointer __old_finish = this->_M_impl._M_finish; // Insertion point: - const auto __ins_idx = __pos - cbegin(); pointer __ins = __old_start + __ins_idx; - // Number of new elements to insert: - const auto __n = size_type(ranges::distance(__rg)); // Number of elements that can fit in unused capacity: const auto __cap = this->_M_impl._M_end_of_storage - __old_finish; if (__cap >= __n) diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 2d34a8d..5c010a4 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -394,6 +394,14 @@ ftms = { }; ftms = { + name = constant_wrapper; + values = { + v = 202506; + cxxmin = 26; + }; +}; + +ftms = { name = has_unique_object_representations; values = { v = 201606; @@ -464,6 +472,10 @@ ftms = { ftms = { name = not_fn; values = { + v = 202306; + cxxmin = 26; + }; + values = { v = 201603; cxxmin = 17; }; @@ -582,6 +594,12 @@ ftms = { ftms = { name = chrono; values = { + v = 202306; + cxxmin = 26; + hosted = yes; + cxx11abi = yes; + }; + values = { v = 201907; cxxmin = 20; hosted = yes; @@ -595,6 +613,21 @@ ftms = { }; ftms = { + // Unofficial macro for chrono features supported for old string ABI. + name = chrono_cxx20; + values = { + v = 202306; + cxxmin = 26; + no_stdname = yes; + }; + values = { + v = 201800; + cxxmin = 20; + no_stdname = yes; + }; +}; + +ftms = { name = execution; values = { v = 201902; // FIXME: should be 201603L @@ -649,7 +682,7 @@ ftms = { }; values = { v = 1; - /* For when there's no gthread. */ + // For when there is no gthread. cxxmin = 17; hosted = yes; gthread = no; @@ -733,6 +766,14 @@ ftms = { }; ftms = { + name = is_sufficiently_aligned; + values = { + v = 202411; + cxxmin = 26; + }; +}; + +ftms = { name = atomic_flag_test; values = { v = 201907; @@ -760,6 +801,10 @@ ftms = { ftms = { name = atomic_ref; values = { + v = 202411; + cxxmin = 26; + }; + values = { v = 201806; cxxmin = 20; }; @@ -777,6 +822,10 @@ ftms = { ftms = { name = bind_front; values = { + v = 202306; + cxxmin = 26; + }; + values = { v = 201907; cxxmin = 20; }; @@ -785,6 +834,10 @@ ftms = { ftms = { name = bind_back; values = { + v = 202306; + cxxmin = 26; + }; + values = { v = 202202; cxxmin = 23; extra_cond = "__cpp_explicit_this_parameter"; @@ -826,8 +879,12 @@ ftms = { ftms = { name = concepts; + // 201806 P0898R3 Standard Library Concepts + // 201907 P1754R1 Rename concepts to standard_case for C++20 + // 202002 P1964R2 Wording for boolean-testable + // 202207 P2404R3 Move-only types for equality_comparable_with, etc. values = { - v = 202002; + v = 202207; cxxmin = 20; extra_cond = "__cpp_concepts >= 201907L"; }; @@ -836,12 +893,17 @@ ftms = { // Moved down here (after concepts) by topological sort. ftms = { name = optional; - values = { + values = { // optional<T&> + v = 202506; + cxxmin = 26; + extra_cond = "__glibcxx_concepts"; + }; + values = { // monadic operations v = 202110; cxxmin = 23; extra_cond = "__glibcxx_concepts"; }; - values = { + values = { // full constexpr support v = 202106; cxxmin = 20; }; @@ -852,6 +914,14 @@ ftms = { }; ftms = { + name = optional_range_support; + values = { + v = 202406; + cxxmin = 26; + }; +}; + +ftms = { name = destroying_delete; values = { v = 201806; @@ -999,14 +1069,46 @@ ftms = { ftms = { name = mdspan; - no_stdname = true; // FIXME: remove values = { - v = 1; // FIXME: 202207 + v = 202406; + cxxmin = 26; + }; + values = { + v = 202207; cxxmin = 23; }; }; ftms = { + name = aligned_accessor; + values = { + v = 202411; + cxxmin = 26; + extra_cond = "__glibcxx_assume_aligned " + "&& __glibcxx_is_sufficiently_aligned"; + }; +}; + +// Purely internal macro padded layouts. +ftms = { + name = padded_layouts; + no_stdname = true; // internal + values = { + v = 202403; + cxxmin = 26; + }; +}; + +ftms = { + name = submdspan; + values = { + v = 202411; + cxxmin = 26; + extra_cond = "__glibcxx_constant_wrapper >= 202506L"; + }; +}; + +ftms = { name = ssize; values = { v = 201902; @@ -1084,6 +1186,10 @@ ftms = { ftms = { name = shift; values = { + v = 202202; + cxxmin = 23; + }; + values = { v = 201806; cxxmin = 20; }; @@ -1363,7 +1469,7 @@ ftms = { v = 201907; cxxmin = 20; hosted = yes; - extra_cond = "__glibcxx_atomic_wait || _GLIBCXX_HAVE_POSIX_SEMAPHORE"; + extra_cond = "__glibcxx_atomic_wait"; }; }; @@ -1661,6 +1767,22 @@ ftms = { }; ftms = { + name = ranges_starts_ends_with; + values = { + v = 202106; + cxxmin = 23; + }; +}; + +ftms = { + name = ranges_indices; + values = { + v = 202506; + cxxmin = 26; + }; +}; + +ftms = { name = constexpr_bitset; values = { v = 202202; @@ -1704,6 +1826,22 @@ ftms = { }; ftms = { + name = common_reference; + values = { + v = 202302; + cxxmin = 20; // We treat P2655R3 as a DR against C++20. + }; +}; + +ftms = { + name = common_reference_wrapper; + values = { + v = 202302; + cxxmin = 20; // We treat P2655R3 as a DR against C++20. + }; +}; + +ftms = { name = formatters; values = { v = 202302; @@ -1748,6 +1886,23 @@ ftms = { }; ftms = { + name = copyable_function; + values = { + v = 202306; + cxxmin = 26; + hosted = yes; + }; +}; + +ftms = { + name = function_ref; + values = { + v = 202306; + cxxmin = 26; + }; +}; + +ftms = { name = out_ptr; values = { v = 202311; @@ -1758,7 +1913,7 @@ ftms = { ftms = { name = print; values = { - v = 202211; + v = 202406; cxxmin = 23; hosted = yes; }; @@ -1785,6 +1940,14 @@ ftms = { }; ftms = { + name = start_lifetime_as; + values = { + v = 202207; + cxxmin = 23; + }; +}; + +ftms = { name = string_contains; values = { v = 202011; @@ -1803,6 +1966,14 @@ ftms = { }; ftms = { + name = string_subview; + values = { + v = 202506; + cxxmin = 26; + }; +}; + +ftms = { name = to_underlying; values = { v = 202102; @@ -1832,6 +2003,15 @@ ftms = { }; ftms = { + name = observable_checkpoint; + values = { + v = 202506; + cxxmin = 26; + extra_cond = "__has_builtin(__builtin_observable_checkpoint)"; + }; +}; + +ftms = { name = algorithm_default_value_type; values = { v = 202403; @@ -1849,6 +2029,14 @@ ftms = { }; ftms = { + name = debugging; + values = { + v = 202403; + cxxmin = 26; + }; +}; + +ftms = { name = fstream_native_handle; values = { v = 202306; @@ -1952,6 +2140,105 @@ ftms = { }; }; +ftms = { + name = inplace_vector; + values = { + v = 202406; + cxxmin = 26; + }; +}; + +ftms = { + name = indirect; + values = { + v = 202502; + cxxmin = 26; + hosted = yes; + }; +}; + +ftms = { + name = polymorphic; + values = { + v = 202502; + cxxmin = 26; + hosted = yes; + }; +}; + +ftms = { + name = smart_ptr_owner_equality; + values = { + v = 202306; + cxxmin = 26; + hosted = yes; + }; +}; + +ftms = { + name = sstream_from_string_view; + values = { + v = 202306; + cxxmin = 26; + hosted = yes; + }; +}; + +ftms = { + name = type_order; + values = { + v = 202506; + cxxmin = 26; + extra_cond = "__has_builtin(__builtin_type_order) " + "&& __cpp_lib_three_way_comparison >= 201907L"; + }; +}; + +ftms = { + name = exception_ptr_cast; + values = { + v = 202506; + cxxmin = 26; + }; +}; + +ftms = { + name = bitset; // ...construct from string_view + values = { + v = 202306; + cxxmin = 26; + }; +}; + +ftms = { + name = constexpr_exceptions; + // TODO Remove when PR121114 is resolved + no_stdname = true; + values = { + v = 1; // TODO 202411; + cxxmin = 26; + extra_cond = "__cpp_constexpr_exceptions >= 202411L"; + }; +}; + +ftms = { + name = philox_engine; + values = { + v = 202406; + cxxmin = 26; + extra_cond = "__SIZEOF_INT128__"; + }; +}; + +ftms = { + name = is_implicit_lifetime; + values = { + v = 202302; + cxxmin = 23; + extra_cond = "__has_builtin(__builtin_is_implicit_lifetime)"; + }; +}; + // Standard test specifications. stds[97] = ">= 199711L"; stds[03] = ">= 199711L"; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 24831f7..26d0689 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -57,7 +57,7 @@ # define __cpp_lib_incomplete_container_elements 201505L # endif # endif -#endif /* !defined(__cpp_lib_incomplete_container_elements) && defined(__glibcxx_want_incomplete_container_elements) */ +#endif /* !defined(__cpp_lib_incomplete_container_elements) */ #undef __glibcxx_want_incomplete_container_elements #if !defined(__cpp_lib_uncaught_exceptions) @@ -67,7 +67,7 @@ # define __cpp_lib_uncaught_exceptions 201411L # endif # endif -#endif /* !defined(__cpp_lib_uncaught_exceptions) && defined(__glibcxx_want_uncaught_exceptions) */ +#endif /* !defined(__cpp_lib_uncaught_exceptions) */ #undef __glibcxx_want_uncaught_exceptions #if !defined(__cpp_lib_allocator_traits_is_always_equal) @@ -77,7 +77,7 @@ # define __cpp_lib_allocator_traits_is_always_equal 201411L # endif # endif -#endif /* !defined(__cpp_lib_allocator_traits_is_always_equal) && defined(__glibcxx_want_allocator_traits_is_always_equal) */ +#endif /* !defined(__cpp_lib_allocator_traits_is_always_equal) */ #undef __glibcxx_want_allocator_traits_is_always_equal #if !defined(__cpp_lib_is_null_pointer) @@ -87,7 +87,7 @@ # define __cpp_lib_is_null_pointer 201309L # endif # endif -#endif /* !defined(__cpp_lib_is_null_pointer) && defined(__glibcxx_want_is_null_pointer) */ +#endif /* !defined(__cpp_lib_is_null_pointer) */ #undef __glibcxx_want_is_null_pointer #if !defined(__cpp_lib_result_of_sfinae) @@ -97,7 +97,7 @@ # define __cpp_lib_result_of_sfinae 201210L # endif # endif -#endif /* !defined(__cpp_lib_result_of_sfinae) && defined(__glibcxx_want_result_of_sfinae) */ +#endif /* !defined(__cpp_lib_result_of_sfinae) */ #undef __glibcxx_want_result_of_sfinae #if !defined(__cpp_lib_shared_ptr_arrays) @@ -112,7 +112,7 @@ # define __cpp_lib_shared_ptr_arrays 201611L # endif # endif -#endif /* !defined(__cpp_lib_shared_ptr_arrays) && defined(__glibcxx_want_shared_ptr_arrays) */ +#endif /* !defined(__cpp_lib_shared_ptr_arrays) */ #undef __glibcxx_want_shared_ptr_arrays #if !defined(__cpp_lib_is_swappable) @@ -122,7 +122,7 @@ # define __cpp_lib_is_swappable 201603L # endif # endif -#endif /* !defined(__cpp_lib_is_swappable) && defined(__glibcxx_want_is_swappable) */ +#endif /* !defined(__cpp_lib_is_swappable) */ #undef __glibcxx_want_is_swappable #if !defined(__cpp_lib_void_t) @@ -132,7 +132,7 @@ # define __cpp_lib_void_t 201411L # endif # endif -#endif /* !defined(__cpp_lib_void_t) && defined(__glibcxx_want_void_t) */ +#endif /* !defined(__cpp_lib_void_t) */ #undef __glibcxx_want_void_t #if !defined(__cpp_lib_enable_shared_from_this) @@ -142,7 +142,7 @@ # define __cpp_lib_enable_shared_from_this 201603L # endif # endif -#endif /* !defined(__cpp_lib_enable_shared_from_this) && defined(__glibcxx_want_enable_shared_from_this) */ +#endif /* !defined(__cpp_lib_enable_shared_from_this) */ #undef __glibcxx_want_enable_shared_from_this #if !defined(__cpp_lib_math_spec_funcs) @@ -152,7 +152,7 @@ # define __STDCPP_MATH_SPEC_FUNCS__ 201003L # endif # endif -#endif /* !defined(__cpp_lib_math_spec_funcs) && defined(__glibcxx_want_math_spec_funcs) */ +#endif /* !defined(__cpp_lib_math_spec_funcs) */ #undef __glibcxx_want_math_spec_funcs #if !defined(__cpp_lib_coroutine) @@ -162,7 +162,7 @@ # define __cpp_lib_coroutine 201902L # endif # endif -#endif /* !defined(__cpp_lib_coroutine) && defined(__glibcxx_want_coroutine) */ +#endif /* !defined(__cpp_lib_coroutine) */ #undef __glibcxx_want_coroutine #if !defined(__cpp_lib_exchange_function) @@ -172,7 +172,7 @@ # define __cpp_lib_exchange_function 201304L # endif # endif -#endif /* !defined(__cpp_lib_exchange_function) && defined(__glibcxx_want_exchange_function) */ +#endif /* !defined(__cpp_lib_exchange_function) */ #undef __glibcxx_want_exchange_function #if !defined(__cpp_lib_integer_sequence) @@ -182,7 +182,7 @@ # define __cpp_lib_integer_sequence 201304L # endif # endif -#endif /* !defined(__cpp_lib_integer_sequence) && defined(__glibcxx_want_integer_sequence) */ +#endif /* !defined(__cpp_lib_integer_sequence) */ #undef __glibcxx_want_integer_sequence #if !defined(__cpp_lib_integral_constant_callable) @@ -192,7 +192,7 @@ # define __cpp_lib_integral_constant_callable 201304L # endif # endif -#endif /* !defined(__cpp_lib_integral_constant_callable) && defined(__glibcxx_want_integral_constant_callable) */ +#endif /* !defined(__cpp_lib_integral_constant_callable) */ #undef __glibcxx_want_integral_constant_callable #if !defined(__cpp_lib_is_final) @@ -202,7 +202,7 @@ # define __cpp_lib_is_final 201402L # endif # endif -#endif /* !defined(__cpp_lib_is_final) && defined(__glibcxx_want_is_final) */ +#endif /* !defined(__cpp_lib_is_final) */ #undef __glibcxx_want_is_final #if !defined(__cpp_lib_make_reverse_iterator) @@ -212,7 +212,7 @@ # define __cpp_lib_make_reverse_iterator 201402L # endif # endif -#endif /* !defined(__cpp_lib_make_reverse_iterator) && defined(__glibcxx_want_make_reverse_iterator) */ +#endif /* !defined(__cpp_lib_make_reverse_iterator) */ #undef __glibcxx_want_make_reverse_iterator #if !defined(__cpp_lib_null_iterators) @@ -222,7 +222,7 @@ # define __cpp_lib_null_iterators 201304L # endif # endif -#endif /* !defined(__cpp_lib_null_iterators) && defined(__glibcxx_want_null_iterators) */ +#endif /* !defined(__cpp_lib_null_iterators) */ #undef __glibcxx_want_null_iterators #if !defined(__cpp_lib_transformation_trait_aliases) @@ -232,7 +232,7 @@ # define __cpp_lib_transformation_trait_aliases 201304L # endif # endif -#endif /* !defined(__cpp_lib_transformation_trait_aliases) && defined(__glibcxx_want_transformation_trait_aliases) */ +#endif /* !defined(__cpp_lib_transformation_trait_aliases) */ #undef __glibcxx_want_transformation_trait_aliases #if !defined(__cpp_lib_transparent_operators) @@ -242,7 +242,7 @@ # define __cpp_lib_transparent_operators 201510L # endif # endif -#endif /* !defined(__cpp_lib_transparent_operators) && defined(__glibcxx_want_transparent_operators) */ +#endif /* !defined(__cpp_lib_transparent_operators) */ #undef __glibcxx_want_transparent_operators #if !defined(__cpp_lib_tuple_element_t) @@ -252,7 +252,7 @@ # define __cpp_lib_tuple_element_t 201402L # endif # endif -#endif /* !defined(__cpp_lib_tuple_element_t) && defined(__glibcxx_want_tuple_element_t) */ +#endif /* !defined(__cpp_lib_tuple_element_t) */ #undef __glibcxx_want_tuple_element_t #if !defined(__cpp_lib_tuples_by_type) @@ -262,7 +262,7 @@ # define __cpp_lib_tuples_by_type 201304L # endif # endif -#endif /* !defined(__cpp_lib_tuples_by_type) && defined(__glibcxx_want_tuples_by_type) */ +#endif /* !defined(__cpp_lib_tuples_by_type) */ #undef __glibcxx_want_tuples_by_type #if !defined(__cpp_lib_robust_nonmodifying_seq_ops) @@ -272,7 +272,7 @@ # define __cpp_lib_robust_nonmodifying_seq_ops 201304L # endif # endif -#endif /* !defined(__cpp_lib_robust_nonmodifying_seq_ops) && defined(__glibcxx_want_robust_nonmodifying_seq_ops) */ +#endif /* !defined(__cpp_lib_robust_nonmodifying_seq_ops) */ #undef __glibcxx_want_robust_nonmodifying_seq_ops #if !defined(__cpp_lib_to_chars) @@ -287,7 +287,7 @@ # define __cpp_lib_to_chars 201611L # endif # endif -#endif /* !defined(__cpp_lib_to_chars) && defined(__glibcxx_want_to_chars) */ +#endif /* !defined(__cpp_lib_to_chars) */ #undef __glibcxx_want_to_chars #if !defined(__cpp_lib_chrono_udls) @@ -297,7 +297,7 @@ # define __cpp_lib_chrono_udls 201304L # endif # endif -#endif /* !defined(__cpp_lib_chrono_udls) && defined(__glibcxx_want_chrono_udls) */ +#endif /* !defined(__cpp_lib_chrono_udls) */ #undef __glibcxx_want_chrono_udls #if !defined(__cpp_lib_complex_udls) @@ -307,7 +307,7 @@ # define __cpp_lib_complex_udls 201309L # endif # endif -#endif /* !defined(__cpp_lib_complex_udls) && defined(__glibcxx_want_complex_udls) */ +#endif /* !defined(__cpp_lib_complex_udls) */ #undef __glibcxx_want_complex_udls #if !defined(__cpp_lib_generic_associative_lookup) @@ -317,7 +317,7 @@ # define __cpp_lib_generic_associative_lookup 201304L # endif # endif -#endif /* !defined(__cpp_lib_generic_associative_lookup) && defined(__glibcxx_want_generic_associative_lookup) */ +#endif /* !defined(__cpp_lib_generic_associative_lookup) */ #undef __glibcxx_want_generic_associative_lookup #if !defined(__cpp_lib_make_unique) @@ -327,7 +327,7 @@ # define __cpp_lib_make_unique 201304L # endif # endif -#endif /* !defined(__cpp_lib_make_unique) && defined(__glibcxx_want_make_unique) */ +#endif /* !defined(__cpp_lib_make_unique) */ #undef __glibcxx_want_make_unique #if !defined(__cpp_lib_quoted_string_io) @@ -337,7 +337,7 @@ # define __cpp_lib_quoted_string_io 201304L # endif # endif -#endif /* !defined(__cpp_lib_quoted_string_io) && defined(__glibcxx_want_quoted_string_io) */ +#endif /* !defined(__cpp_lib_quoted_string_io) */ #undef __glibcxx_want_quoted_string_io #if !defined(__cpp_lib_shared_timed_mutex) @@ -347,7 +347,7 @@ # define __cpp_lib_shared_timed_mutex 201402L # endif # endif -#endif /* !defined(__cpp_lib_shared_timed_mutex) && defined(__glibcxx_want_shared_timed_mutex) */ +#endif /* !defined(__cpp_lib_shared_timed_mutex) */ #undef __glibcxx_want_shared_timed_mutex #if !defined(__cpp_lib_string_udls) @@ -357,7 +357,7 @@ # define __cpp_lib_string_udls 201304L # endif # endif -#endif /* !defined(__cpp_lib_string_udls) && defined(__glibcxx_want_string_udls) */ +#endif /* !defined(__cpp_lib_string_udls) */ #undef __glibcxx_want_string_udls #if !defined(__cpp_lib_addressof_constexpr) @@ -367,7 +367,7 @@ # define __cpp_lib_addressof_constexpr 201603L # endif # endif -#endif /* !defined(__cpp_lib_addressof_constexpr) && defined(__glibcxx_want_addressof_constexpr) */ +#endif /* !defined(__cpp_lib_addressof_constexpr) */ #undef __glibcxx_want_addressof_constexpr #if !defined(__cpp_lib_any) @@ -377,7 +377,7 @@ # define __cpp_lib_any 201606L # endif # endif -#endif /* !defined(__cpp_lib_any) && defined(__glibcxx_want_any) */ +#endif /* !defined(__cpp_lib_any) */ #undef __glibcxx_want_any #if !defined(__cpp_lib_apply) @@ -387,7 +387,7 @@ # define __cpp_lib_apply 201603L # endif # endif -#endif /* !defined(__cpp_lib_apply) && defined(__glibcxx_want_apply) */ +#endif /* !defined(__cpp_lib_apply) */ #undef __glibcxx_want_apply #if !defined(__cpp_lib_as_const) @@ -397,7 +397,7 @@ # define __cpp_lib_as_const 201510L # endif # endif -#endif /* !defined(__cpp_lib_as_const) && defined(__glibcxx_want_as_const) */ +#endif /* !defined(__cpp_lib_as_const) */ #undef __glibcxx_want_as_const #if !defined(__cpp_lib_atomic_is_always_lock_free) @@ -407,7 +407,7 @@ # define __cpp_lib_atomic_is_always_lock_free 201603L # endif # endif -#endif /* !defined(__cpp_lib_atomic_is_always_lock_free) && defined(__glibcxx_want_atomic_is_always_lock_free) */ +#endif /* !defined(__cpp_lib_atomic_is_always_lock_free) */ #undef __glibcxx_want_atomic_is_always_lock_free #if !defined(__cpp_lib_bool_constant) @@ -417,7 +417,7 @@ # define __cpp_lib_bool_constant 201505L # endif # endif -#endif /* !defined(__cpp_lib_bool_constant) && defined(__glibcxx_want_bool_constant) */ +#endif /* !defined(__cpp_lib_bool_constant) */ #undef __glibcxx_want_bool_constant #if !defined(__cpp_lib_byte) @@ -427,9 +427,19 @@ # define __cpp_lib_byte 201603L # endif # endif -#endif /* !defined(__cpp_lib_byte) && defined(__glibcxx_want_byte) */ +#endif /* !defined(__cpp_lib_byte) */ #undef __glibcxx_want_byte +#if !defined(__cpp_lib_constant_wrapper) +# if (__cplusplus > 202302L) +# define __glibcxx_constant_wrapper 202506L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constant_wrapper) +# define __cpp_lib_constant_wrapper 202506L +# endif +# endif +#endif /* !defined(__cpp_lib_constant_wrapper) */ +#undef __glibcxx_want_constant_wrapper + #if !defined(__cpp_lib_has_unique_object_representations) # if (__cplusplus >= 201703L) && (defined(_GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP)) # define __glibcxx_has_unique_object_representations 201606L @@ -437,7 +447,7 @@ # define __cpp_lib_has_unique_object_representations 201606L # endif # endif -#endif /* !defined(__cpp_lib_has_unique_object_representations) && defined(__glibcxx_want_has_unique_object_representations) */ +#endif /* !defined(__cpp_lib_has_unique_object_representations) */ #undef __glibcxx_want_has_unique_object_representations #if !defined(__cpp_lib_hardware_interference_size) @@ -447,7 +457,7 @@ # define __cpp_lib_hardware_interference_size 201703L # endif # endif -#endif /* !defined(__cpp_lib_hardware_interference_size) && defined(__glibcxx_want_hardware_interference_size) */ +#endif /* !defined(__cpp_lib_hardware_interference_size) */ #undef __glibcxx_want_hardware_interference_size #if !defined(__cpp_lib_invoke) @@ -457,7 +467,7 @@ # define __cpp_lib_invoke 201411L # endif # endif -#endif /* !defined(__cpp_lib_invoke) && defined(__glibcxx_want_invoke) */ +#endif /* !defined(__cpp_lib_invoke) */ #undef __glibcxx_want_invoke #if !defined(__cpp_lib_is_aggregate) @@ -467,7 +477,7 @@ # define __cpp_lib_is_aggregate 201703L # endif # endif -#endif /* !defined(__cpp_lib_is_aggregate) && defined(__glibcxx_want_is_aggregate) */ +#endif /* !defined(__cpp_lib_is_aggregate) */ #undef __glibcxx_want_is_aggregate #if !defined(__cpp_lib_is_invocable) @@ -477,7 +487,7 @@ # define __cpp_lib_is_invocable 201703L # endif # endif -#endif /* !defined(__cpp_lib_is_invocable) && defined(__glibcxx_want_is_invocable) */ +#endif /* !defined(__cpp_lib_is_invocable) */ #undef __glibcxx_want_is_invocable #if !defined(__cpp_lib_launder) @@ -487,7 +497,7 @@ # define __cpp_lib_launder 201606L # endif # endif -#endif /* !defined(__cpp_lib_launder) && defined(__glibcxx_want_launder) */ +#endif /* !defined(__cpp_lib_launder) */ #undef __glibcxx_want_launder #if !defined(__cpp_lib_logical_traits) @@ -497,7 +507,7 @@ # define __cpp_lib_logical_traits 201510L # endif # endif -#endif /* !defined(__cpp_lib_logical_traits) && defined(__glibcxx_want_logical_traits) */ +#endif /* !defined(__cpp_lib_logical_traits) */ #undef __glibcxx_want_logical_traits #if !defined(__cpp_lib_make_from_tuple) @@ -507,17 +517,22 @@ # define __cpp_lib_make_from_tuple 201606L # endif # endif -#endif /* !defined(__cpp_lib_make_from_tuple) && defined(__glibcxx_want_make_from_tuple) */ +#endif /* !defined(__cpp_lib_make_from_tuple) */ #undef __glibcxx_want_make_from_tuple #if !defined(__cpp_lib_not_fn) -# if (__cplusplus >= 201703L) +# if (__cplusplus > 202302L) +# define __glibcxx_not_fn 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_not_fn) +# define __cpp_lib_not_fn 202306L +# endif +# elif (__cplusplus >= 201703L) # define __glibcxx_not_fn 201603L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_not_fn) # define __cpp_lib_not_fn 201603L # endif # endif -#endif /* !defined(__cpp_lib_not_fn) && defined(__glibcxx_want_not_fn) */ +#endif /* !defined(__cpp_lib_not_fn) */ #undef __glibcxx_want_not_fn #if !defined(__cpp_lib_type_trait_variable_templates) @@ -527,7 +542,7 @@ # define __cpp_lib_type_trait_variable_templates 201510L # endif # endif -#endif /* !defined(__cpp_lib_type_trait_variable_templates) && defined(__glibcxx_want_type_trait_variable_templates) */ +#endif /* !defined(__cpp_lib_type_trait_variable_templates) */ #undef __glibcxx_want_type_trait_variable_templates #if !defined(__cpp_lib_variant) @@ -547,7 +562,7 @@ # define __cpp_lib_variant 202102L # endif # endif -#endif /* !defined(__cpp_lib_variant) && defined(__glibcxx_want_variant) */ +#endif /* !defined(__cpp_lib_variant) */ #undef __glibcxx_want_variant #if !defined(__cpp_lib_lcm) @@ -557,7 +572,7 @@ # define __cpp_lib_lcm 201606L # endif # endif -#endif /* !defined(__cpp_lib_lcm) && defined(__glibcxx_want_lcm) */ +#endif /* !defined(__cpp_lib_lcm) */ #undef __glibcxx_want_lcm #if !defined(__cpp_lib_gcd) @@ -567,7 +582,7 @@ # define __cpp_lib_gcd 201606L # endif # endif -#endif /* !defined(__cpp_lib_gcd) && defined(__glibcxx_want_gcd) */ +#endif /* !defined(__cpp_lib_gcd) */ #undef __glibcxx_want_gcd #if !defined(__cpp_lib_gcd_lcm) @@ -577,7 +592,7 @@ # define __cpp_lib_gcd_lcm 201606L # endif # endif -#endif /* !defined(__cpp_lib_gcd_lcm) && defined(__glibcxx_want_gcd_lcm) */ +#endif /* !defined(__cpp_lib_gcd_lcm) */ #undef __glibcxx_want_gcd_lcm #if !defined(__cpp_lib_raw_memory_algorithms) @@ -592,7 +607,7 @@ # define __cpp_lib_raw_memory_algorithms 201606L # endif # endif -#endif /* !defined(__cpp_lib_raw_memory_algorithms) && defined(__glibcxx_want_raw_memory_algorithms) */ +#endif /* !defined(__cpp_lib_raw_memory_algorithms) */ #undef __glibcxx_want_raw_memory_algorithms #if !defined(__cpp_lib_array_constexpr) @@ -607,7 +622,7 @@ # define __cpp_lib_array_constexpr 201803L # endif # endif -#endif /* !defined(__cpp_lib_array_constexpr) && defined(__glibcxx_want_array_constexpr) */ +#endif /* !defined(__cpp_lib_array_constexpr) */ #undef __glibcxx_want_array_constexpr #if !defined(__cpp_lib_nonmember_container_access) @@ -617,7 +632,7 @@ # define __cpp_lib_nonmember_container_access 201411L # endif # endif -#endif /* !defined(__cpp_lib_nonmember_container_access) && defined(__glibcxx_want_nonmember_container_access) */ +#endif /* !defined(__cpp_lib_nonmember_container_access) */ #undef __glibcxx_want_nonmember_container_access #if !defined(__cpp_lib_clamp) @@ -627,7 +642,7 @@ # define __cpp_lib_clamp 201603L # endif # endif -#endif /* !defined(__cpp_lib_clamp) && defined(__glibcxx_want_clamp) */ +#endif /* !defined(__cpp_lib_clamp) */ #undef __glibcxx_want_clamp #if !defined(__cpp_lib_sample) @@ -637,7 +652,7 @@ # define __cpp_lib_sample 201603L # endif # endif -#endif /* !defined(__cpp_lib_sample) && defined(__glibcxx_want_sample) */ +#endif /* !defined(__cpp_lib_sample) */ #undef __glibcxx_want_sample #if !defined(__cpp_lib_boyer_moore_searcher) @@ -647,11 +662,16 @@ # define __cpp_lib_boyer_moore_searcher 201603L # endif # endif -#endif /* !defined(__cpp_lib_boyer_moore_searcher) && defined(__glibcxx_want_boyer_moore_searcher) */ +#endif /* !defined(__cpp_lib_boyer_moore_searcher) */ #undef __glibcxx_want_boyer_moore_searcher #if !defined(__cpp_lib_chrono) -# if (__cplusplus >= 202002L) && _GLIBCXX_USE_CXX11_ABI && _GLIBCXX_HOSTED +# if (__cplusplus > 202302L) && _GLIBCXX_USE_CXX11_ABI && _GLIBCXX_HOSTED +# define __glibcxx_chrono 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_chrono) +# define __cpp_lib_chrono 202306L +# endif +# elif (__cplusplus >= 202002L) && _GLIBCXX_USE_CXX11_ABI && _GLIBCXX_HOSTED # define __glibcxx_chrono 201907L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_chrono) # define __cpp_lib_chrono 201907L @@ -662,9 +682,22 @@ # define __cpp_lib_chrono 201611L # endif # endif -#endif /* !defined(__cpp_lib_chrono) && defined(__glibcxx_want_chrono) */ +#endif /* !defined(__cpp_lib_chrono) */ #undef __glibcxx_want_chrono +#if !defined(__cpp_lib_chrono_cxx20) +# if (__cplusplus > 202302L) +# define __glibcxx_chrono_cxx20 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_chrono_cxx20) +# endif +# elif (__cplusplus >= 202002L) +# define __glibcxx_chrono_cxx20 201800L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_chrono_cxx20) +# endif +# endif +#endif /* !defined(__cpp_lib_chrono_cxx20) */ +#undef __glibcxx_want_chrono_cxx20 + #if !defined(__cpp_lib_execution) # if (__cplusplus >= 201703L) && _GLIBCXX_HOSTED # define __glibcxx_execution 201902L @@ -672,7 +705,7 @@ # define __cpp_lib_execution 201902L # endif # endif -#endif /* !defined(__cpp_lib_execution) && defined(__glibcxx_want_execution) */ +#endif /* !defined(__cpp_lib_execution) */ #undef __glibcxx_want_execution #if !defined(__cpp_lib_filesystem) @@ -682,7 +715,7 @@ # define __cpp_lib_filesystem 201703L # endif # endif -#endif /* !defined(__cpp_lib_filesystem) && defined(__glibcxx_want_filesystem) */ +#endif /* !defined(__cpp_lib_filesystem) */ #undef __glibcxx_want_filesystem #if !defined(__cpp_lib_hypot) @@ -692,7 +725,7 @@ # define __cpp_lib_hypot 201603L # endif # endif -#endif /* !defined(__cpp_lib_hypot) && defined(__glibcxx_want_hypot) */ +#endif /* !defined(__cpp_lib_hypot) */ #undef __glibcxx_want_hypot #if !defined(__cpp_lib_map_try_emplace) @@ -702,7 +735,7 @@ # define __cpp_lib_map_try_emplace 201411L # endif # endif -#endif /* !defined(__cpp_lib_map_try_emplace) && defined(__glibcxx_want_map_try_emplace) */ +#endif /* !defined(__cpp_lib_map_try_emplace) */ #undef __glibcxx_want_map_try_emplace #if !defined(__cpp_lib_math_special_functions) @@ -712,7 +745,7 @@ # define __cpp_lib_math_special_functions 201603L # endif # endif -#endif /* !defined(__cpp_lib_math_special_functions) && defined(__glibcxx_want_math_special_functions) */ +#endif /* !defined(__cpp_lib_math_special_functions) */ #undef __glibcxx_want_math_special_functions #if !defined(__cpp_lib_memory_resource) @@ -727,7 +760,7 @@ # define __cpp_lib_memory_resource 1L # endif # endif -#endif /* !defined(__cpp_lib_memory_resource) && defined(__glibcxx_want_memory_resource) */ +#endif /* !defined(__cpp_lib_memory_resource) */ #undef __glibcxx_want_memory_resource #if !defined(__cpp_lib_node_extract) @@ -737,7 +770,7 @@ # define __cpp_lib_node_extract 201606L # endif # endif -#endif /* !defined(__cpp_lib_node_extract) && defined(__glibcxx_want_node_extract) */ +#endif /* !defined(__cpp_lib_node_extract) */ #undef __glibcxx_want_node_extract #if !defined(__cpp_lib_parallel_algorithm) @@ -747,7 +780,7 @@ # define __cpp_lib_parallel_algorithm 201603L # endif # endif -#endif /* !defined(__cpp_lib_parallel_algorithm) && defined(__glibcxx_want_parallel_algorithm) */ +#endif /* !defined(__cpp_lib_parallel_algorithm) */ #undef __glibcxx_want_parallel_algorithm #if !defined(__cpp_lib_scoped_lock) @@ -757,7 +790,7 @@ # define __cpp_lib_scoped_lock 201703L # endif # endif -#endif /* !defined(__cpp_lib_scoped_lock) && defined(__glibcxx_want_scoped_lock) */ +#endif /* !defined(__cpp_lib_scoped_lock) */ #undef __glibcxx_want_scoped_lock #if !defined(__cpp_lib_shared_mutex) @@ -767,7 +800,7 @@ # define __cpp_lib_shared_mutex 201505L # endif # endif -#endif /* !defined(__cpp_lib_shared_mutex) && defined(__glibcxx_want_shared_mutex) */ +#endif /* !defined(__cpp_lib_shared_mutex) */ #undef __glibcxx_want_shared_mutex #if !defined(__cpp_lib_shared_ptr_weak_type) @@ -777,7 +810,7 @@ # define __cpp_lib_shared_ptr_weak_type 201606L # endif # endif -#endif /* !defined(__cpp_lib_shared_ptr_weak_type) && defined(__glibcxx_want_shared_ptr_weak_type) */ +#endif /* !defined(__cpp_lib_shared_ptr_weak_type) */ #undef __glibcxx_want_shared_ptr_weak_type #if !defined(__cpp_lib_string_view) @@ -792,7 +825,7 @@ # define __cpp_lib_string_view 201803L # endif # endif -#endif /* !defined(__cpp_lib_string_view) && defined(__glibcxx_want_string_view) */ +#endif /* !defined(__cpp_lib_string_view) */ #undef __glibcxx_want_string_view #if !defined(__cpp_lib_unordered_map_try_emplace) @@ -802,7 +835,7 @@ # define __cpp_lib_unordered_map_try_emplace 201411L # endif # endif -#endif /* !defined(__cpp_lib_unordered_map_try_emplace) && defined(__glibcxx_want_unordered_map_try_emplace) */ +#endif /* !defined(__cpp_lib_unordered_map_try_emplace) */ #undef __glibcxx_want_unordered_map_try_emplace #if !defined(__cpp_lib_assume_aligned) @@ -812,9 +845,19 @@ # define __cpp_lib_assume_aligned 201811L # endif # endif -#endif /* !defined(__cpp_lib_assume_aligned) && defined(__glibcxx_want_assume_aligned) */ +#endif /* !defined(__cpp_lib_assume_aligned) */ #undef __glibcxx_want_assume_aligned +#if !defined(__cpp_lib_is_sufficiently_aligned) +# if (__cplusplus > 202302L) +# define __glibcxx_is_sufficiently_aligned 202411L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_sufficiently_aligned) +# define __cpp_lib_is_sufficiently_aligned 202411L +# endif +# endif +#endif /* !defined(__cpp_lib_is_sufficiently_aligned) */ +#undef __glibcxx_want_is_sufficiently_aligned + #if !defined(__cpp_lib_atomic_flag_test) # if (__cplusplus >= 202002L) # define __glibcxx_atomic_flag_test 201907L @@ -822,7 +865,7 @@ # define __cpp_lib_atomic_flag_test 201907L # endif # endif -#endif /* !defined(__cpp_lib_atomic_flag_test) && defined(__glibcxx_want_atomic_flag_test) */ +#endif /* !defined(__cpp_lib_atomic_flag_test) */ #undef __glibcxx_want_atomic_flag_test #if !defined(__cpp_lib_atomic_float) @@ -832,7 +875,7 @@ # define __cpp_lib_atomic_float 201711L # endif # endif -#endif /* !defined(__cpp_lib_atomic_float) && defined(__glibcxx_want_atomic_float) */ +#endif /* !defined(__cpp_lib_atomic_float) */ #undef __glibcxx_want_atomic_float #if !defined(__cpp_lib_atomic_lock_free_type_aliases) @@ -842,17 +885,22 @@ # define __cpp_lib_atomic_lock_free_type_aliases 201907L # endif # endif -#endif /* !defined(__cpp_lib_atomic_lock_free_type_aliases) && defined(__glibcxx_want_atomic_lock_free_type_aliases) */ +#endif /* !defined(__cpp_lib_atomic_lock_free_type_aliases) */ #undef __glibcxx_want_atomic_lock_free_type_aliases #if !defined(__cpp_lib_atomic_ref) -# if (__cplusplus >= 202002L) +# if (__cplusplus > 202302L) +# define __glibcxx_atomic_ref 202411L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_atomic_ref) +# define __cpp_lib_atomic_ref 202411L +# endif +# elif (__cplusplus >= 202002L) # define __glibcxx_atomic_ref 201806L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_atomic_ref) # define __cpp_lib_atomic_ref 201806L # endif # endif -#endif /* !defined(__cpp_lib_atomic_ref) && defined(__glibcxx_want_atomic_ref) */ +#endif /* !defined(__cpp_lib_atomic_ref) */ #undef __glibcxx_want_atomic_ref #if !defined(__cpp_lib_atomic_value_initialization) @@ -862,27 +910,37 @@ # define __cpp_lib_atomic_value_initialization 201911L # endif # endif -#endif /* !defined(__cpp_lib_atomic_value_initialization) && defined(__glibcxx_want_atomic_value_initialization) */ +#endif /* !defined(__cpp_lib_atomic_value_initialization) */ #undef __glibcxx_want_atomic_value_initialization #if !defined(__cpp_lib_bind_front) -# if (__cplusplus >= 202002L) +# if (__cplusplus > 202302L) +# define __glibcxx_bind_front 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_bind_front) +# define __cpp_lib_bind_front 202306L +# endif +# elif (__cplusplus >= 202002L) # define __glibcxx_bind_front 201907L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_bind_front) # define __cpp_lib_bind_front 201907L # endif # endif -#endif /* !defined(__cpp_lib_bind_front) && defined(__glibcxx_want_bind_front) */ +#endif /* !defined(__cpp_lib_bind_front) */ #undef __glibcxx_want_bind_front #if !defined(__cpp_lib_bind_back) -# if (__cplusplus >= 202100L) && (__cpp_explicit_this_parameter) +# if (__cplusplus > 202302L) +# define __glibcxx_bind_back 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_bind_back) +# define __cpp_lib_bind_back 202306L +# endif +# elif (__cplusplus >= 202100L) && (__cpp_explicit_this_parameter) # define __glibcxx_bind_back 202202L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_bind_back) # define __cpp_lib_bind_back 202202L # endif # endif -#endif /* !defined(__cpp_lib_bind_back) && defined(__glibcxx_want_bind_back) */ +#endif /* !defined(__cpp_lib_bind_back) */ #undef __glibcxx_want_bind_back #if !defined(__cpp_lib_starts_ends_with) @@ -892,7 +950,7 @@ # define __cpp_lib_starts_ends_with 201711L # endif # endif -#endif /* !defined(__cpp_lib_starts_ends_with) && defined(__glibcxx_want_starts_ends_with) */ +#endif /* !defined(__cpp_lib_starts_ends_with) */ #undef __glibcxx_want_starts_ends_with #if !defined(__cpp_lib_bit_cast) @@ -902,7 +960,7 @@ # define __cpp_lib_bit_cast 201806L # endif # endif -#endif /* !defined(__cpp_lib_bit_cast) && defined(__glibcxx_want_bit_cast) */ +#endif /* !defined(__cpp_lib_bit_cast) */ #undef __glibcxx_want_bit_cast #if !defined(__cpp_lib_bitops) @@ -912,7 +970,7 @@ # define __cpp_lib_bitops 201907L # endif # endif -#endif /* !defined(__cpp_lib_bitops) && defined(__glibcxx_want_bitops) */ +#endif /* !defined(__cpp_lib_bitops) */ #undef __glibcxx_want_bitops #if !defined(__cpp_lib_bounded_array_traits) @@ -922,21 +980,26 @@ # define __cpp_lib_bounded_array_traits 201902L # endif # endif -#endif /* !defined(__cpp_lib_bounded_array_traits) && defined(__glibcxx_want_bounded_array_traits) */ +#endif /* !defined(__cpp_lib_bounded_array_traits) */ #undef __glibcxx_want_bounded_array_traits #if !defined(__cpp_lib_concepts) # if (__cplusplus >= 202002L) && (__cpp_concepts >= 201907L) -# define __glibcxx_concepts 202002L +# define __glibcxx_concepts 202207L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_concepts) -# define __cpp_lib_concepts 202002L +# define __cpp_lib_concepts 202207L # endif # endif -#endif /* !defined(__cpp_lib_concepts) && defined(__glibcxx_want_concepts) */ +#endif /* !defined(__cpp_lib_concepts) */ #undef __glibcxx_want_concepts #if !defined(__cpp_lib_optional) -# if (__cplusplus >= 202100L) && (__glibcxx_concepts) +# if (__cplusplus > 202302L) && (__glibcxx_concepts) +# define __glibcxx_optional 202506L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_optional) +# define __cpp_lib_optional 202506L +# endif +# elif (__cplusplus >= 202100L) && (__glibcxx_concepts) # define __glibcxx_optional 202110L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_optional) # define __cpp_lib_optional 202110L @@ -952,9 +1015,19 @@ # define __cpp_lib_optional 201606L # endif # endif -#endif /* !defined(__cpp_lib_optional) && defined(__glibcxx_want_optional) */ +#endif /* !defined(__cpp_lib_optional) */ #undef __glibcxx_want_optional +#if !defined(__cpp_lib_optional_range_support) +# if (__cplusplus > 202302L) +# define __glibcxx_optional_range_support 202406L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_optional_range_support) +# define __cpp_lib_optional_range_support 202406L +# endif +# endif +#endif /* !defined(__cpp_lib_optional_range_support) */ +#undef __glibcxx_want_optional_range_support + #if !defined(__cpp_lib_destroying_delete) # if (__cplusplus >= 202002L) && (__cpp_impl_destroying_delete) # define __glibcxx_destroying_delete 201806L @@ -962,7 +1035,7 @@ # define __cpp_lib_destroying_delete 201806L # endif # endif -#endif /* !defined(__cpp_lib_destroying_delete) && defined(__glibcxx_want_destroying_delete) */ +#endif /* !defined(__cpp_lib_destroying_delete) */ #undef __glibcxx_want_destroying_delete #if !defined(__cpp_lib_constexpr_string_view) @@ -972,7 +1045,7 @@ # define __cpp_lib_constexpr_string_view 201811L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_string_view) && defined(__glibcxx_want_constexpr_string_view) */ +#endif /* !defined(__cpp_lib_constexpr_string_view) */ #undef __glibcxx_want_constexpr_string_view #if !defined(__cpp_lib_endian) @@ -982,7 +1055,7 @@ # define __cpp_lib_endian 201907L # endif # endif -#endif /* !defined(__cpp_lib_endian) && defined(__glibcxx_want_endian) */ +#endif /* !defined(__cpp_lib_endian) */ #undef __glibcxx_want_endian #if !defined(__cpp_lib_int_pow2) @@ -992,7 +1065,7 @@ # define __cpp_lib_int_pow2 202002L # endif # endif -#endif /* !defined(__cpp_lib_int_pow2) && defined(__glibcxx_want_int_pow2) */ +#endif /* !defined(__cpp_lib_int_pow2) */ #undef __glibcxx_want_int_pow2 #if !defined(__cpp_lib_integer_comparison_functions) @@ -1002,7 +1075,7 @@ # define __cpp_lib_integer_comparison_functions 202002L # endif # endif -#endif /* !defined(__cpp_lib_integer_comparison_functions) && defined(__glibcxx_want_integer_comparison_functions) */ +#endif /* !defined(__cpp_lib_integer_comparison_functions) */ #undef __glibcxx_want_integer_comparison_functions #if !defined(__cpp_lib_is_constant_evaluated) @@ -1012,7 +1085,7 @@ # define __cpp_lib_is_constant_evaluated 201811L # endif # endif -#endif /* !defined(__cpp_lib_is_constant_evaluated) && defined(__glibcxx_want_is_constant_evaluated) */ +#endif /* !defined(__cpp_lib_is_constant_evaluated) */ #undef __glibcxx_want_is_constant_evaluated #if !defined(__cpp_lib_constexpr_char_traits) @@ -1027,7 +1100,7 @@ # define __cpp_lib_constexpr_char_traits 201611L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_char_traits) && defined(__glibcxx_want_constexpr_char_traits) */ +#endif /* !defined(__cpp_lib_constexpr_char_traits) */ #undef __glibcxx_want_constexpr_char_traits #if !defined(__cpp_lib_is_layout_compatible) @@ -1037,7 +1110,7 @@ # define __cpp_lib_is_layout_compatible 201907L # endif # endif -#endif /* !defined(__cpp_lib_is_layout_compatible) && defined(__glibcxx_want_is_layout_compatible) */ +#endif /* !defined(__cpp_lib_is_layout_compatible) */ #undef __glibcxx_want_is_layout_compatible #if !defined(__cpp_lib_is_nothrow_convertible) @@ -1047,7 +1120,7 @@ # define __cpp_lib_is_nothrow_convertible 201806L # endif # endif -#endif /* !defined(__cpp_lib_is_nothrow_convertible) && defined(__glibcxx_want_is_nothrow_convertible) */ +#endif /* !defined(__cpp_lib_is_nothrow_convertible) */ #undef __glibcxx_want_is_nothrow_convertible #if !defined(__cpp_lib_is_pointer_interconvertible) @@ -1057,7 +1130,7 @@ # define __cpp_lib_is_pointer_interconvertible 201907L # endif # endif -#endif /* !defined(__cpp_lib_is_pointer_interconvertible) && defined(__glibcxx_want_is_pointer_interconvertible) */ +#endif /* !defined(__cpp_lib_is_pointer_interconvertible) */ #undef __glibcxx_want_is_pointer_interconvertible #if !defined(__cpp_lib_math_constants) @@ -1067,7 +1140,7 @@ # define __cpp_lib_math_constants 201907L # endif # endif -#endif /* !defined(__cpp_lib_math_constants) && defined(__glibcxx_want_math_constants) */ +#endif /* !defined(__cpp_lib_math_constants) */ #undef __glibcxx_want_math_constants #if !defined(__cpp_lib_make_obj_using_allocator) @@ -1076,7 +1149,7 @@ # if defined(__glibcxx_want_all) || defined(__glibcxx_want_make_obj_using_allocator) # endif # endif -#endif /* !defined(__cpp_lib_make_obj_using_allocator) && defined(__glibcxx_want_make_obj_using_allocator) */ +#endif /* !defined(__cpp_lib_make_obj_using_allocator) */ #undef __glibcxx_want_make_obj_using_allocator #if !defined(__cpp_lib_remove_cvref) @@ -1086,7 +1159,7 @@ # define __cpp_lib_remove_cvref 201711L # endif # endif -#endif /* !defined(__cpp_lib_remove_cvref) && defined(__glibcxx_want_remove_cvref) */ +#endif /* !defined(__cpp_lib_remove_cvref) */ #undef __glibcxx_want_remove_cvref #if !defined(__cpp_lib_source_location) @@ -1096,7 +1169,7 @@ # define __cpp_lib_source_location 201907L # endif # endif -#endif /* !defined(__cpp_lib_source_location) && defined(__glibcxx_want_source_location) */ +#endif /* !defined(__cpp_lib_source_location) */ #undef __glibcxx_want_source_location #if !defined(__cpp_lib_span) @@ -1111,18 +1184,53 @@ # define __cpp_lib_span 202002L # endif # endif -#endif /* !defined(__cpp_lib_span) && defined(__glibcxx_want_span) */ +#endif /* !defined(__cpp_lib_span) */ #undef __glibcxx_want_span #if !defined(__cpp_lib_mdspan) -# if (__cplusplus >= 202100L) -# define __glibcxx_mdspan 1L +# if (__cplusplus > 202302L) +# define __glibcxx_mdspan 202406L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_mdspan) +# define __cpp_lib_mdspan 202406L +# endif +# elif (__cplusplus >= 202100L) +# define __glibcxx_mdspan 202207L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_mdspan) +# define __cpp_lib_mdspan 202207L # endif # endif -#endif /* !defined(__cpp_lib_mdspan) && defined(__glibcxx_want_mdspan) */ +#endif /* !defined(__cpp_lib_mdspan) */ #undef __glibcxx_want_mdspan +#if !defined(__cpp_lib_aligned_accessor) +# if (__cplusplus > 202302L) && (__glibcxx_assume_aligned && __glibcxx_is_sufficiently_aligned) +# define __glibcxx_aligned_accessor 202411L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_aligned_accessor) +# define __cpp_lib_aligned_accessor 202411L +# endif +# endif +#endif /* !defined(__cpp_lib_aligned_accessor) */ +#undef __glibcxx_want_aligned_accessor + +#if !defined(__cpp_lib_padded_layouts) +# if (__cplusplus > 202302L) +# define __glibcxx_padded_layouts 202403L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_padded_layouts) +# endif +# endif +#endif /* !defined(__cpp_lib_padded_layouts) */ +#undef __glibcxx_want_padded_layouts + +#if !defined(__cpp_lib_submdspan) +# if (__cplusplus > 202302L) && (__glibcxx_constant_wrapper >= 202506L) +# define __glibcxx_submdspan 202411L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_submdspan) +# define __cpp_lib_submdspan 202411L +# endif +# endif +#endif /* !defined(__cpp_lib_submdspan) */ +#undef __glibcxx_want_submdspan + #if !defined(__cpp_lib_ssize) # if (__cplusplus >= 202002L) # define __glibcxx_ssize 201902L @@ -1130,7 +1238,7 @@ # define __cpp_lib_ssize 201902L # endif # endif -#endif /* !defined(__cpp_lib_ssize) && defined(__glibcxx_want_ssize) */ +#endif /* !defined(__cpp_lib_ssize) */ #undef __glibcxx_want_ssize #if !defined(__cpp_lib_three_way_comparison) @@ -1140,7 +1248,7 @@ # define __cpp_lib_three_way_comparison 201907L # endif # endif -#endif /* !defined(__cpp_lib_three_way_comparison) && defined(__glibcxx_want_three_way_comparison) */ +#endif /* !defined(__cpp_lib_three_way_comparison) */ #undef __glibcxx_want_three_way_comparison #if !defined(__cpp_lib_to_address) @@ -1150,7 +1258,7 @@ # define __cpp_lib_to_address 201711L # endif # endif -#endif /* !defined(__cpp_lib_to_address) && defined(__glibcxx_want_to_address) */ +#endif /* !defined(__cpp_lib_to_address) */ #undef __glibcxx_want_to_address #if !defined(__cpp_lib_to_array) @@ -1160,7 +1268,7 @@ # define __cpp_lib_to_array 201907L # endif # endif -#endif /* !defined(__cpp_lib_to_array) && defined(__glibcxx_want_to_array) */ +#endif /* !defined(__cpp_lib_to_array) */ #undef __glibcxx_want_to_array #if !defined(__cpp_lib_type_identity) @@ -1170,7 +1278,7 @@ # define __cpp_lib_type_identity 201806L # endif # endif -#endif /* !defined(__cpp_lib_type_identity) && defined(__glibcxx_want_type_identity) */ +#endif /* !defined(__cpp_lib_type_identity) */ #undef __glibcxx_want_type_identity #if !defined(__cpp_lib_unwrap_ref) @@ -1180,7 +1288,7 @@ # define __cpp_lib_unwrap_ref 201811L # endif # endif -#endif /* !defined(__cpp_lib_unwrap_ref) && defined(__glibcxx_want_unwrap_ref) */ +#endif /* !defined(__cpp_lib_unwrap_ref) */ #undef __glibcxx_want_unwrap_ref #if !defined(__cpp_lib_constexpr_iterator) @@ -1190,7 +1298,7 @@ # define __cpp_lib_constexpr_iterator 201811L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_iterator) && defined(__glibcxx_want_constexpr_iterator) */ +#endif /* !defined(__cpp_lib_constexpr_iterator) */ #undef __glibcxx_want_constexpr_iterator #if !defined(__cpp_lib_interpolate) @@ -1200,7 +1308,7 @@ # define __cpp_lib_interpolate 201902L # endif # endif -#endif /* !defined(__cpp_lib_interpolate) && defined(__glibcxx_want_interpolate) */ +#endif /* !defined(__cpp_lib_interpolate) */ #undef __glibcxx_want_interpolate #if !defined(__cpp_lib_constexpr_utility) @@ -1210,17 +1318,22 @@ # define __cpp_lib_constexpr_utility 201811L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_utility) && defined(__glibcxx_want_constexpr_utility) */ +#endif /* !defined(__cpp_lib_constexpr_utility) */ #undef __glibcxx_want_constexpr_utility #if !defined(__cpp_lib_shift) -# if (__cplusplus >= 202002L) +# if (__cplusplus >= 202100L) +# define __glibcxx_shift 202202L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_shift) +# define __cpp_lib_shift 202202L +# endif +# elif (__cplusplus >= 202002L) # define __glibcxx_shift 201806L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_shift) # define __cpp_lib_shift 201806L # endif # endif -#endif /* !defined(__cpp_lib_shift) && defined(__glibcxx_want_shift) */ +#endif /* !defined(__cpp_lib_shift) */ #undef __glibcxx_want_shift #if !defined(__cpp_lib_ranges) @@ -1240,7 +1353,7 @@ # define __cpp_lib_ranges 202110L # endif # endif -#endif /* !defined(__cpp_lib_ranges) && defined(__glibcxx_want_ranges) */ +#endif /* !defined(__cpp_lib_ranges) */ #undef __glibcxx_want_ranges #if !defined(__cpp_lib_constexpr_numeric) @@ -1250,7 +1363,7 @@ # define __cpp_lib_constexpr_numeric 201911L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_numeric) && defined(__glibcxx_want_constexpr_numeric) */ +#endif /* !defined(__cpp_lib_constexpr_numeric) */ #undef __glibcxx_want_constexpr_numeric #if !defined(__cpp_lib_constexpr_functional) @@ -1260,7 +1373,7 @@ # define __cpp_lib_constexpr_functional 201907L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_functional) && defined(__glibcxx_want_constexpr_functional) */ +#endif /* !defined(__cpp_lib_constexpr_functional) */ #undef __glibcxx_want_constexpr_functional #if !defined(__cpp_lib_constexpr_algorithms) @@ -1275,7 +1388,7 @@ # define __cpp_lib_constexpr_algorithms 201806L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_algorithms) && defined(__glibcxx_want_constexpr_algorithms) */ +#endif /* !defined(__cpp_lib_constexpr_algorithms) */ #undef __glibcxx_want_constexpr_algorithms #if !defined(__cpp_lib_constexpr_tuple) @@ -1285,7 +1398,7 @@ # define __cpp_lib_constexpr_tuple 201811L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_tuple) && defined(__glibcxx_want_constexpr_tuple) */ +#endif /* !defined(__cpp_lib_constexpr_tuple) */ #undef __glibcxx_want_constexpr_tuple #if !defined(__cpp_lib_constexpr_memory) @@ -1300,7 +1413,7 @@ # define __cpp_lib_constexpr_memory 201811L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_memory) && defined(__glibcxx_want_constexpr_memory) */ +#endif /* !defined(__cpp_lib_constexpr_memory) */ #undef __glibcxx_want_constexpr_memory #if !defined(__cpp_lib_atomic_shared_ptr) @@ -1310,7 +1423,7 @@ # define __cpp_lib_atomic_shared_ptr 201711L # endif # endif -#endif /* !defined(__cpp_lib_atomic_shared_ptr) && defined(__glibcxx_want_atomic_shared_ptr) */ +#endif /* !defined(__cpp_lib_atomic_shared_ptr) */ #undef __glibcxx_want_atomic_shared_ptr #if !defined(__cpp_lib_atomic_wait) @@ -1325,7 +1438,7 @@ # define __cpp_lib_atomic_wait 201907L # endif # endif -#endif /* !defined(__cpp_lib_atomic_wait) && defined(__glibcxx_want_atomic_wait) */ +#endif /* !defined(__cpp_lib_atomic_wait) */ #undef __glibcxx_want_atomic_wait #if !defined(__cpp_lib_barrier) @@ -1335,7 +1448,7 @@ # define __cpp_lib_barrier 201907L # endif # endif -#endif /* !defined(__cpp_lib_barrier) && defined(__glibcxx_want_barrier) */ +#endif /* !defined(__cpp_lib_barrier) */ #undef __glibcxx_want_barrier #if !defined(__cpp_lib_format) @@ -1350,7 +1463,7 @@ # define __cpp_lib_format 202304L # endif # endif -#endif /* !defined(__cpp_lib_format) && defined(__glibcxx_want_format) */ +#endif /* !defined(__cpp_lib_format) */ #undef __glibcxx_want_format #if !defined(__cpp_lib_format_uchar) @@ -1360,7 +1473,7 @@ # define __cpp_lib_format_uchar 202311L # endif # endif -#endif /* !defined(__cpp_lib_format_uchar) && defined(__glibcxx_want_format_uchar) */ +#endif /* !defined(__cpp_lib_format_uchar) */ #undef __glibcxx_want_format_uchar #if !defined(__cpp_lib_constexpr_complex) @@ -1370,7 +1483,7 @@ # define __cpp_lib_constexpr_complex 201711L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_complex) && defined(__glibcxx_want_constexpr_complex) */ +#endif /* !defined(__cpp_lib_constexpr_complex) */ #undef __glibcxx_want_constexpr_complex #if !defined(__cpp_lib_constexpr_dynamic_alloc) @@ -1380,7 +1493,7 @@ # define __cpp_lib_constexpr_dynamic_alloc 201907L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_dynamic_alloc) && defined(__glibcxx_want_constexpr_dynamic_alloc) */ +#endif /* !defined(__cpp_lib_constexpr_dynamic_alloc) */ #undef __glibcxx_want_constexpr_dynamic_alloc #if !defined(__cpp_lib_constexpr_string) @@ -1400,7 +1513,7 @@ # define __cpp_lib_constexpr_string 201611L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_string) && defined(__glibcxx_want_constexpr_string) */ +#endif /* !defined(__cpp_lib_constexpr_string) */ #undef __glibcxx_want_constexpr_string #if !defined(__cpp_lib_constexpr_vector) @@ -1410,7 +1523,7 @@ # define __cpp_lib_constexpr_vector 201907L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_vector) && defined(__glibcxx_want_constexpr_vector) */ +#endif /* !defined(__cpp_lib_constexpr_vector) */ #undef __glibcxx_want_constexpr_vector #if !defined(__cpp_lib_constrained_equality) @@ -1425,7 +1538,7 @@ # define __cpp_lib_constrained_equality 202403L # endif # endif -#endif /* !defined(__cpp_lib_constrained_equality) && defined(__glibcxx_want_constrained_equality) */ +#endif /* !defined(__cpp_lib_constrained_equality) */ #undef __glibcxx_want_constrained_equality #if !defined(__cpp_lib_erase_if) @@ -1435,7 +1548,7 @@ # define __cpp_lib_erase_if 202002L # endif # endif -#endif /* !defined(__cpp_lib_erase_if) && defined(__glibcxx_want_erase_if) */ +#endif /* !defined(__cpp_lib_erase_if) */ #undef __glibcxx_want_erase_if #if !defined(__cpp_lib_generic_unordered_lookup) @@ -1445,7 +1558,7 @@ # define __cpp_lib_generic_unordered_lookup 201811L # endif # endif -#endif /* !defined(__cpp_lib_generic_unordered_lookup) && defined(__glibcxx_want_generic_unordered_lookup) */ +#endif /* !defined(__cpp_lib_generic_unordered_lookup) */ #undef __glibcxx_want_generic_unordered_lookup #if !defined(__cpp_lib_jthread) @@ -1455,7 +1568,7 @@ # define __cpp_lib_jthread 201911L # endif # endif -#endif /* !defined(__cpp_lib_jthread) && defined(__glibcxx_want_jthread) */ +#endif /* !defined(__cpp_lib_jthread) */ #undef __glibcxx_want_jthread #if !defined(__cpp_lib_latch) @@ -1465,7 +1578,7 @@ # define __cpp_lib_latch 201907L # endif # endif -#endif /* !defined(__cpp_lib_latch) && defined(__glibcxx_want_latch) */ +#endif /* !defined(__cpp_lib_latch) */ #undef __glibcxx_want_latch #if !defined(__cpp_lib_list_remove_return_type) @@ -1475,7 +1588,7 @@ # define __cpp_lib_list_remove_return_type 201806L # endif # endif -#endif /* !defined(__cpp_lib_list_remove_return_type) && defined(__glibcxx_want_list_remove_return_type) */ +#endif /* !defined(__cpp_lib_list_remove_return_type) */ #undef __glibcxx_want_list_remove_return_type #if !defined(__cpp_lib_polymorphic_allocator) @@ -1485,7 +1598,7 @@ # define __cpp_lib_polymorphic_allocator 201902L # endif # endif -#endif /* !defined(__cpp_lib_polymorphic_allocator) && defined(__glibcxx_want_polymorphic_allocator) */ +#endif /* !defined(__cpp_lib_polymorphic_allocator) */ #undef __glibcxx_want_polymorphic_allocator #if !defined(__cpp_lib_move_iterator_concept) @@ -1495,17 +1608,17 @@ # define __cpp_lib_move_iterator_concept 202207L # endif # endif -#endif /* !defined(__cpp_lib_move_iterator_concept) && defined(__glibcxx_want_move_iterator_concept) */ +#endif /* !defined(__cpp_lib_move_iterator_concept) */ #undef __glibcxx_want_move_iterator_concept #if !defined(__cpp_lib_semaphore) -# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED && (__glibcxx_atomic_wait || _GLIBCXX_HAVE_POSIX_SEMAPHORE) +# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED && (__glibcxx_atomic_wait) # define __glibcxx_semaphore 201907L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_semaphore) # define __cpp_lib_semaphore 201907L # endif # endif -#endif /* !defined(__cpp_lib_semaphore) && defined(__glibcxx_want_semaphore) */ +#endif /* !defined(__cpp_lib_semaphore) */ #undef __glibcxx_want_semaphore #if !defined(__cpp_lib_smart_ptr_for_overwrite) @@ -1515,7 +1628,7 @@ # define __cpp_lib_smart_ptr_for_overwrite 202002L # endif # endif -#endif /* !defined(__cpp_lib_smart_ptr_for_overwrite) && defined(__glibcxx_want_smart_ptr_for_overwrite) */ +#endif /* !defined(__cpp_lib_smart_ptr_for_overwrite) */ #undef __glibcxx_want_smart_ptr_for_overwrite #if !defined(__cpp_lib_syncbuf) @@ -1525,7 +1638,7 @@ # define __cpp_lib_syncbuf 201803L # endif # endif -#endif /* !defined(__cpp_lib_syncbuf) && defined(__glibcxx_want_syncbuf) */ +#endif /* !defined(__cpp_lib_syncbuf) */ #undef __glibcxx_want_syncbuf #if !defined(__cpp_lib_byteswap) @@ -1535,7 +1648,7 @@ # define __cpp_lib_byteswap 202110L # endif # endif -#endif /* !defined(__cpp_lib_byteswap) && defined(__glibcxx_want_byteswap) */ +#endif /* !defined(__cpp_lib_byteswap) */ #undef __glibcxx_want_byteswap #if !defined(__cpp_lib_constexpr_charconv) @@ -1545,7 +1658,7 @@ # define __cpp_lib_constexpr_charconv 202207L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_charconv) && defined(__glibcxx_want_constexpr_charconv) */ +#endif /* !defined(__cpp_lib_constexpr_charconv) */ #undef __glibcxx_want_constexpr_charconv #if !defined(__cpp_lib_constexpr_typeinfo) @@ -1555,7 +1668,7 @@ # define __cpp_lib_constexpr_typeinfo 202106L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_typeinfo) && defined(__glibcxx_want_constexpr_typeinfo) */ +#endif /* !defined(__cpp_lib_constexpr_typeinfo) */ #undef __glibcxx_want_constexpr_typeinfo #if !defined(__cpp_lib_expected) @@ -1565,7 +1678,7 @@ # define __cpp_lib_expected 202211L # endif # endif -#endif /* !defined(__cpp_lib_expected) && defined(__glibcxx_want_expected) */ +#endif /* !defined(__cpp_lib_expected) */ #undef __glibcxx_want_expected #if !defined(__cpp_lib_format_ranges) @@ -1575,7 +1688,7 @@ # define __cpp_lib_format_ranges 202207L # endif # endif -#endif /* !defined(__cpp_lib_format_ranges) && defined(__glibcxx_want_format_ranges) */ +#endif /* !defined(__cpp_lib_format_ranges) */ #undef __glibcxx_want_format_ranges #if !defined(__cpp_lib_freestanding_algorithm) @@ -1585,7 +1698,7 @@ # define __cpp_lib_freestanding_algorithm 202311L # endif # endif -#endif /* !defined(__cpp_lib_freestanding_algorithm) && defined(__glibcxx_want_freestanding_algorithm) */ +#endif /* !defined(__cpp_lib_freestanding_algorithm) */ #undef __glibcxx_want_freestanding_algorithm #if !defined(__cpp_lib_freestanding_array) @@ -1595,7 +1708,7 @@ # define __cpp_lib_freestanding_array 202311L # endif # endif -#endif /* !defined(__cpp_lib_freestanding_array) && defined(__glibcxx_want_freestanding_array) */ +#endif /* !defined(__cpp_lib_freestanding_array) */ #undef __glibcxx_want_freestanding_array #if !defined(__cpp_lib_freestanding_cstring) @@ -1605,7 +1718,7 @@ # define __cpp_lib_freestanding_cstring 202311L # endif # endif -#endif /* !defined(__cpp_lib_freestanding_cstring) && defined(__glibcxx_want_freestanding_cstring) */ +#endif /* !defined(__cpp_lib_freestanding_cstring) */ #undef __glibcxx_want_freestanding_cstring #if !defined(__cpp_lib_freestanding_expected) @@ -1615,7 +1728,7 @@ # define __cpp_lib_freestanding_expected 202311L # endif # endif -#endif /* !defined(__cpp_lib_freestanding_expected) && defined(__glibcxx_want_freestanding_expected) */ +#endif /* !defined(__cpp_lib_freestanding_expected) */ #undef __glibcxx_want_freestanding_expected #if !defined(__cpp_lib_freestanding_optional) @@ -1625,7 +1738,7 @@ # define __cpp_lib_freestanding_optional 202311L # endif # endif -#endif /* !defined(__cpp_lib_freestanding_optional) && defined(__glibcxx_want_freestanding_optional) */ +#endif /* !defined(__cpp_lib_freestanding_optional) */ #undef __glibcxx_want_freestanding_optional #if !defined(__cpp_lib_freestanding_string_view) @@ -1635,7 +1748,7 @@ # define __cpp_lib_freestanding_string_view 202311L # endif # endif -#endif /* !defined(__cpp_lib_freestanding_string_view) && defined(__glibcxx_want_freestanding_string_view) */ +#endif /* !defined(__cpp_lib_freestanding_string_view) */ #undef __glibcxx_want_freestanding_string_view #if !defined(__cpp_lib_freestanding_variant) @@ -1645,7 +1758,7 @@ # define __cpp_lib_freestanding_variant 202311L # endif # endif -#endif /* !defined(__cpp_lib_freestanding_variant) && defined(__glibcxx_want_freestanding_variant) */ +#endif /* !defined(__cpp_lib_freestanding_variant) */ #undef __glibcxx_want_freestanding_variant #if !defined(__cpp_lib_invoke_r) @@ -1655,7 +1768,7 @@ # define __cpp_lib_invoke_r 202106L # endif # endif -#endif /* !defined(__cpp_lib_invoke_r) && defined(__glibcxx_want_invoke_r) */ +#endif /* !defined(__cpp_lib_invoke_r) */ #undef __glibcxx_want_invoke_r #if !defined(__cpp_lib_is_scoped_enum) @@ -1665,7 +1778,7 @@ # define __cpp_lib_is_scoped_enum 202011L # endif # endif -#endif /* !defined(__cpp_lib_is_scoped_enum) && defined(__glibcxx_want_is_scoped_enum) */ +#endif /* !defined(__cpp_lib_is_scoped_enum) */ #undef __glibcxx_want_is_scoped_enum #if !defined(__cpp_lib_reference_from_temporary) @@ -1675,7 +1788,7 @@ # define __cpp_lib_reference_from_temporary 202202L # endif # endif -#endif /* !defined(__cpp_lib_reference_from_temporary) && defined(__glibcxx_want_reference_from_temporary) */ +#endif /* !defined(__cpp_lib_reference_from_temporary) */ #undef __glibcxx_want_reference_from_temporary #if !defined(__cpp_lib_containers_ranges) @@ -1685,7 +1798,7 @@ # define __cpp_lib_containers_ranges 202202L # endif # endif -#endif /* !defined(__cpp_lib_containers_ranges) && defined(__glibcxx_want_containers_ranges) */ +#endif /* !defined(__cpp_lib_containers_ranges) */ #undef __glibcxx_want_containers_ranges #if !defined(__cpp_lib_ranges_to_container) @@ -1695,7 +1808,7 @@ # define __cpp_lib_ranges_to_container 202202L # endif # endif -#endif /* !defined(__cpp_lib_ranges_to_container) && defined(__glibcxx_want_ranges_to_container) */ +#endif /* !defined(__cpp_lib_ranges_to_container) */ #undef __glibcxx_want_ranges_to_container #if !defined(__cpp_lib_ranges_zip) @@ -1705,7 +1818,7 @@ # define __cpp_lib_ranges_zip 202110L # endif # endif -#endif /* !defined(__cpp_lib_ranges_zip) && defined(__glibcxx_want_ranges_zip) */ +#endif /* !defined(__cpp_lib_ranges_zip) */ #undef __glibcxx_want_ranges_zip #if !defined(__cpp_lib_ranges_chunk) @@ -1715,7 +1828,7 @@ # define __cpp_lib_ranges_chunk 202202L # endif # endif -#endif /* !defined(__cpp_lib_ranges_chunk) && defined(__glibcxx_want_ranges_chunk) */ +#endif /* !defined(__cpp_lib_ranges_chunk) */ #undef __glibcxx_want_ranges_chunk #if !defined(__cpp_lib_ranges_slide) @@ -1725,7 +1838,7 @@ # define __cpp_lib_ranges_slide 202202L # endif # endif -#endif /* !defined(__cpp_lib_ranges_slide) && defined(__glibcxx_want_ranges_slide) */ +#endif /* !defined(__cpp_lib_ranges_slide) */ #undef __glibcxx_want_ranges_slide #if !defined(__cpp_lib_ranges_chunk_by) @@ -1735,7 +1848,7 @@ # define __cpp_lib_ranges_chunk_by 202202L # endif # endif -#endif /* !defined(__cpp_lib_ranges_chunk_by) && defined(__glibcxx_want_ranges_chunk_by) */ +#endif /* !defined(__cpp_lib_ranges_chunk_by) */ #undef __glibcxx_want_ranges_chunk_by #if !defined(__cpp_lib_ranges_join_with) @@ -1745,7 +1858,7 @@ # define __cpp_lib_ranges_join_with 202202L # endif # endif -#endif /* !defined(__cpp_lib_ranges_join_with) && defined(__glibcxx_want_ranges_join_with) */ +#endif /* !defined(__cpp_lib_ranges_join_with) */ #undef __glibcxx_want_ranges_join_with #if !defined(__cpp_lib_ranges_repeat) @@ -1755,7 +1868,7 @@ # define __cpp_lib_ranges_repeat 202207L # endif # endif -#endif /* !defined(__cpp_lib_ranges_repeat) && defined(__glibcxx_want_ranges_repeat) */ +#endif /* !defined(__cpp_lib_ranges_repeat) */ #undef __glibcxx_want_ranges_repeat #if !defined(__cpp_lib_ranges_stride) @@ -1765,7 +1878,7 @@ # define __cpp_lib_ranges_stride 202207L # endif # endif -#endif /* !defined(__cpp_lib_ranges_stride) && defined(__glibcxx_want_ranges_stride) */ +#endif /* !defined(__cpp_lib_ranges_stride) */ #undef __glibcxx_want_ranges_stride #if !defined(__cpp_lib_ranges_cartesian_product) @@ -1775,7 +1888,7 @@ # define __cpp_lib_ranges_cartesian_product 202207L # endif # endif -#endif /* !defined(__cpp_lib_ranges_cartesian_product) && defined(__glibcxx_want_ranges_cartesian_product) */ +#endif /* !defined(__cpp_lib_ranges_cartesian_product) */ #undef __glibcxx_want_ranges_cartesian_product #if !defined(__cpp_lib_ranges_as_rvalue) @@ -1785,7 +1898,7 @@ # define __cpp_lib_ranges_as_rvalue 202207L # endif # endif -#endif /* !defined(__cpp_lib_ranges_as_rvalue) && defined(__glibcxx_want_ranges_as_rvalue) */ +#endif /* !defined(__cpp_lib_ranges_as_rvalue) */ #undef __glibcxx_want_ranges_as_rvalue #if !defined(__cpp_lib_ranges_as_const) @@ -1795,7 +1908,7 @@ # define __cpp_lib_ranges_as_const 202311L # endif # endif -#endif /* !defined(__cpp_lib_ranges_as_const) && defined(__glibcxx_want_ranges_as_const) */ +#endif /* !defined(__cpp_lib_ranges_as_const) */ #undef __glibcxx_want_ranges_as_const #if !defined(__cpp_lib_ranges_enumerate) @@ -1805,7 +1918,7 @@ # define __cpp_lib_ranges_enumerate 202302L # endif # endif -#endif /* !defined(__cpp_lib_ranges_enumerate) && defined(__glibcxx_want_ranges_enumerate) */ +#endif /* !defined(__cpp_lib_ranges_enumerate) */ #undef __glibcxx_want_ranges_enumerate #if !defined(__cpp_lib_ranges_fold) @@ -1815,7 +1928,7 @@ # define __cpp_lib_ranges_fold 202207L # endif # endif -#endif /* !defined(__cpp_lib_ranges_fold) && defined(__glibcxx_want_ranges_fold) */ +#endif /* !defined(__cpp_lib_ranges_fold) */ #undef __glibcxx_want_ranges_fold #if !defined(__cpp_lib_ranges_contains) @@ -1825,7 +1938,7 @@ # define __cpp_lib_ranges_contains 202207L # endif # endif -#endif /* !defined(__cpp_lib_ranges_contains) && defined(__glibcxx_want_ranges_contains) */ +#endif /* !defined(__cpp_lib_ranges_contains) */ #undef __glibcxx_want_ranges_contains #if !defined(__cpp_lib_ranges_iota) @@ -1835,7 +1948,7 @@ # define __cpp_lib_ranges_iota 202202L # endif # endif -#endif /* !defined(__cpp_lib_ranges_iota) && defined(__glibcxx_want_ranges_iota) */ +#endif /* !defined(__cpp_lib_ranges_iota) */ #undef __glibcxx_want_ranges_iota #if !defined(__cpp_lib_ranges_find_last) @@ -1845,9 +1958,29 @@ # define __cpp_lib_ranges_find_last 202207L # endif # endif -#endif /* !defined(__cpp_lib_ranges_find_last) && defined(__glibcxx_want_ranges_find_last) */ +#endif /* !defined(__cpp_lib_ranges_find_last) */ #undef __glibcxx_want_ranges_find_last +#if !defined(__cpp_lib_ranges_starts_ends_with) +# if (__cplusplus >= 202100L) +# define __glibcxx_ranges_starts_ends_with 202106L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_starts_ends_with) +# define __cpp_lib_ranges_starts_ends_with 202106L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_starts_ends_with) */ +#undef __glibcxx_want_ranges_starts_ends_with + +#if !defined(__cpp_lib_ranges_indices) +# if (__cplusplus > 202302L) +# define __glibcxx_ranges_indices 202506L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_ranges_indices) +# define __cpp_lib_ranges_indices 202506L +# endif +# endif +#endif /* !defined(__cpp_lib_ranges_indices) */ +#undef __glibcxx_want_ranges_indices + #if !defined(__cpp_lib_constexpr_bitset) # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED && (__cpp_constexpr_dynamic_alloc) # define __glibcxx_constexpr_bitset 202202L @@ -1855,7 +1988,7 @@ # define __cpp_lib_constexpr_bitset 202202L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_bitset) && defined(__glibcxx_want_constexpr_bitset) */ +#endif /* !defined(__cpp_lib_constexpr_bitset) */ #undef __glibcxx_want_constexpr_bitset #if !defined(__cpp_lib_stdatomic_h) @@ -1865,7 +1998,7 @@ # define __cpp_lib_stdatomic_h 202011L # endif # endif -#endif /* !defined(__cpp_lib_stdatomic_h) && defined(__glibcxx_want_stdatomic_h) */ +#endif /* !defined(__cpp_lib_stdatomic_h) */ #undef __glibcxx_want_stdatomic_h #if !defined(__cpp_lib_adaptor_iterator_pair_constructor) @@ -1875,7 +2008,7 @@ # define __cpp_lib_adaptor_iterator_pair_constructor 202106L # endif # endif -#endif /* !defined(__cpp_lib_adaptor_iterator_pair_constructor) && defined(__glibcxx_want_adaptor_iterator_pair_constructor) */ +#endif /* !defined(__cpp_lib_adaptor_iterator_pair_constructor) */ #undef __glibcxx_want_adaptor_iterator_pair_constructor #if !defined(__cpp_lib_flat_map) @@ -1885,7 +2018,7 @@ # define __cpp_lib_flat_map 202207L # endif # endif -#endif /* !defined(__cpp_lib_flat_map) && defined(__glibcxx_want_flat_map) */ +#endif /* !defined(__cpp_lib_flat_map) */ #undef __glibcxx_want_flat_map #if !defined(__cpp_lib_flat_set) @@ -1895,9 +2028,29 @@ # define __cpp_lib_flat_set 202207L # endif # endif -#endif /* !defined(__cpp_lib_flat_set) && defined(__glibcxx_want_flat_set) */ +#endif /* !defined(__cpp_lib_flat_set) */ #undef __glibcxx_want_flat_set +#if !defined(__cpp_lib_common_reference) +# if (__cplusplus >= 202002L) +# define __glibcxx_common_reference 202302L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_common_reference) +# define __cpp_lib_common_reference 202302L +# endif +# endif +#endif /* !defined(__cpp_lib_common_reference) */ +#undef __glibcxx_want_common_reference + +#if !defined(__cpp_lib_common_reference_wrapper) +# if (__cplusplus >= 202002L) +# define __glibcxx_common_reference_wrapper 202302L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_common_reference_wrapper) +# define __cpp_lib_common_reference_wrapper 202302L +# endif +# endif +#endif /* !defined(__cpp_lib_common_reference_wrapper) */ +#undef __glibcxx_want_common_reference_wrapper + #if !defined(__cpp_lib_formatters) # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED # define __glibcxx_formatters 202302L @@ -1905,7 +2058,7 @@ # define __cpp_lib_formatters 202302L # endif # endif -#endif /* !defined(__cpp_lib_formatters) && defined(__glibcxx_want_formatters) */ +#endif /* !defined(__cpp_lib_formatters) */ #undef __glibcxx_want_formatters #if !defined(__cpp_lib_forward_like) @@ -1915,7 +2068,7 @@ # define __cpp_lib_forward_like 202207L # endif # endif -#endif /* !defined(__cpp_lib_forward_like) && defined(__glibcxx_want_forward_like) */ +#endif /* !defined(__cpp_lib_forward_like) */ #undef __glibcxx_want_forward_like #if !defined(__cpp_lib_generator) @@ -1925,7 +2078,7 @@ # define __cpp_lib_generator 202207L # endif # endif -#endif /* !defined(__cpp_lib_generator) && defined(__glibcxx_want_generator) */ +#endif /* !defined(__cpp_lib_generator) */ #undef __glibcxx_want_generator #if !defined(__cpp_lib_ios_noreplace) @@ -1935,7 +2088,7 @@ # define __cpp_lib_ios_noreplace 202207L # endif # endif -#endif /* !defined(__cpp_lib_ios_noreplace) && defined(__glibcxx_want_ios_noreplace) */ +#endif /* !defined(__cpp_lib_ios_noreplace) */ #undef __glibcxx_want_ios_noreplace #if !defined(__cpp_lib_move_only_function) @@ -1945,9 +2098,29 @@ # define __cpp_lib_move_only_function 202110L # endif # endif -#endif /* !defined(__cpp_lib_move_only_function) && defined(__glibcxx_want_move_only_function) */ +#endif /* !defined(__cpp_lib_move_only_function) */ #undef __glibcxx_want_move_only_function +#if !defined(__cpp_lib_copyable_function) +# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED +# define __glibcxx_copyable_function 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_copyable_function) +# define __cpp_lib_copyable_function 202306L +# endif +# endif +#endif /* !defined(__cpp_lib_copyable_function) */ +#undef __glibcxx_want_copyable_function + +#if !defined(__cpp_lib_function_ref) +# if (__cplusplus > 202302L) +# define __glibcxx_function_ref 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_function_ref) +# define __cpp_lib_function_ref 202306L +# endif +# endif +#endif /* !defined(__cpp_lib_function_ref) */ +#undef __glibcxx_want_function_ref + #if !defined(__cpp_lib_out_ptr) # if (__cplusplus >= 202100L) # define __glibcxx_out_ptr 202311L @@ -1955,17 +2128,17 @@ # define __cpp_lib_out_ptr 202311L # endif # endif -#endif /* !defined(__cpp_lib_out_ptr) && defined(__glibcxx_want_out_ptr) */ +#endif /* !defined(__cpp_lib_out_ptr) */ #undef __glibcxx_want_out_ptr #if !defined(__cpp_lib_print) # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED -# define __glibcxx_print 202211L +# define __glibcxx_print 202406L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_print) -# define __cpp_lib_print 202211L +# define __cpp_lib_print 202406L # endif # endif -#endif /* !defined(__cpp_lib_print) && defined(__glibcxx_want_print) */ +#endif /* !defined(__cpp_lib_print) */ #undef __glibcxx_want_print #if !defined(__cpp_lib_spanstream) @@ -1975,7 +2148,7 @@ # define __cpp_lib_spanstream 202106L # endif # endif -#endif /* !defined(__cpp_lib_spanstream) && defined(__glibcxx_want_spanstream) */ +#endif /* !defined(__cpp_lib_spanstream) */ #undef __glibcxx_want_spanstream #if !defined(__cpp_lib_stacktrace) @@ -1985,9 +2158,19 @@ # define __cpp_lib_stacktrace 202011L # endif # endif -#endif /* !defined(__cpp_lib_stacktrace) && defined(__glibcxx_want_stacktrace) */ +#endif /* !defined(__cpp_lib_stacktrace) */ #undef __glibcxx_want_stacktrace +#if !defined(__cpp_lib_start_lifetime_as) +# if (__cplusplus >= 202100L) +# define __glibcxx_start_lifetime_as 202207L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_start_lifetime_as) +# define __cpp_lib_start_lifetime_as 202207L +# endif +# endif +#endif /* !defined(__cpp_lib_start_lifetime_as) */ +#undef __glibcxx_want_start_lifetime_as + #if !defined(__cpp_lib_string_contains) # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED # define __glibcxx_string_contains 202011L @@ -1995,7 +2178,7 @@ # define __cpp_lib_string_contains 202011L # endif # endif -#endif /* !defined(__cpp_lib_string_contains) && defined(__glibcxx_want_string_contains) */ +#endif /* !defined(__cpp_lib_string_contains) */ #undef __glibcxx_want_string_contains #if !defined(__cpp_lib_string_resize_and_overwrite) @@ -2005,9 +2188,19 @@ # define __cpp_lib_string_resize_and_overwrite 202110L # endif # endif -#endif /* !defined(__cpp_lib_string_resize_and_overwrite) && defined(__glibcxx_want_string_resize_and_overwrite) */ +#endif /* !defined(__cpp_lib_string_resize_and_overwrite) */ #undef __glibcxx_want_string_resize_and_overwrite +#if !defined(__cpp_lib_string_subview) +# if (__cplusplus > 202302L) +# define __glibcxx_string_subview 202506L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_string_subview) +# define __cpp_lib_string_subview 202506L +# endif +# endif +#endif /* !defined(__cpp_lib_string_subview) */ +#undef __glibcxx_want_string_subview + #if !defined(__cpp_lib_to_underlying) # if (__cplusplus >= 202100L) # define __glibcxx_to_underlying 202102L @@ -2015,7 +2208,7 @@ # define __cpp_lib_to_underlying 202102L # endif # endif -#endif /* !defined(__cpp_lib_to_underlying) && defined(__glibcxx_want_to_underlying) */ +#endif /* !defined(__cpp_lib_to_underlying) */ #undef __glibcxx_want_to_underlying #if !defined(__cpp_lib_tuple_like) @@ -2030,7 +2223,7 @@ # define __cpp_lib_tuple_like 202207L # endif # endif -#endif /* !defined(__cpp_lib_tuple_like) && defined(__glibcxx_want_tuple_like) */ +#endif /* !defined(__cpp_lib_tuple_like) */ #undef __glibcxx_want_tuple_like #if !defined(__cpp_lib_unreachable) @@ -2040,9 +2233,19 @@ # define __cpp_lib_unreachable 202202L # endif # endif -#endif /* !defined(__cpp_lib_unreachable) && defined(__glibcxx_want_unreachable) */ +#endif /* !defined(__cpp_lib_unreachable) */ #undef __glibcxx_want_unreachable +#if !defined(__cpp_lib_observable_checkpoint) +# if (__cplusplus > 202302L) && (__has_builtin(__builtin_observable_checkpoint)) +# define __glibcxx_observable_checkpoint 202506L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_observable_checkpoint) +# define __cpp_lib_observable_checkpoint 202506L +# endif +# endif +#endif /* !defined(__cpp_lib_observable_checkpoint) */ +#undef __glibcxx_want_observable_checkpoint + #if !defined(__cpp_lib_algorithm_default_value_type) # if (__cplusplus > 202302L) # define __glibcxx_algorithm_default_value_type 202403L @@ -2050,7 +2253,7 @@ # define __cpp_lib_algorithm_default_value_type 202403L # endif # endif -#endif /* !defined(__cpp_lib_algorithm_default_value_type) && defined(__glibcxx_want_algorithm_default_value_type) */ +#endif /* !defined(__cpp_lib_algorithm_default_value_type) */ #undef __glibcxx_want_algorithm_default_value_type #if !defined(__cpp_lib_constexpr_new) @@ -2060,9 +2263,19 @@ # define __cpp_lib_constexpr_new 202406L # endif # endif -#endif /* !defined(__cpp_lib_constexpr_new) && defined(__glibcxx_want_constexpr_new) */ +#endif /* !defined(__cpp_lib_constexpr_new) */ #undef __glibcxx_want_constexpr_new +#if !defined(__cpp_lib_debugging) +# if (__cplusplus > 202302L) +# define __glibcxx_debugging 202403L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_debugging) +# define __cpp_lib_debugging 202403L +# endif +# endif +#endif /* !defined(__cpp_lib_debugging) */ +#undef __glibcxx_want_debugging + #if !defined(__cpp_lib_fstream_native_handle) # if (__cplusplus > 202302L) && _GLIBCXX_HOSTED # define __glibcxx_fstream_native_handle 202306L @@ -2070,7 +2283,7 @@ # define __cpp_lib_fstream_native_handle 202306L # endif # endif -#endif /* !defined(__cpp_lib_fstream_native_handle) && defined(__glibcxx_want_fstream_native_handle) */ +#endif /* !defined(__cpp_lib_fstream_native_handle) */ #undef __glibcxx_want_fstream_native_handle #if !defined(__cpp_lib_is_virtual_base_of) @@ -2080,7 +2293,7 @@ # define __cpp_lib_is_virtual_base_of 202406L # endif # endif -#endif /* !defined(__cpp_lib_is_virtual_base_of) && defined(__glibcxx_want_is_virtual_base_of) */ +#endif /* !defined(__cpp_lib_is_virtual_base_of) */ #undef __glibcxx_want_is_virtual_base_of #if !defined(__cpp_lib_ranges_cache_latest) @@ -2090,7 +2303,7 @@ # define __cpp_lib_ranges_cache_latest 202411L # endif # endif -#endif /* !defined(__cpp_lib_ranges_cache_latest) && defined(__glibcxx_want_ranges_cache_latest) */ +#endif /* !defined(__cpp_lib_ranges_cache_latest) */ #undef __glibcxx_want_ranges_cache_latest #if !defined(__cpp_lib_ranges_concat) @@ -2100,7 +2313,7 @@ # define __cpp_lib_ranges_concat 202403L # endif # endif -#endif /* !defined(__cpp_lib_ranges_concat) && defined(__glibcxx_want_ranges_concat) */ +#endif /* !defined(__cpp_lib_ranges_concat) */ #undef __glibcxx_want_ranges_concat #if !defined(__cpp_lib_ratio) @@ -2110,7 +2323,7 @@ # define __cpp_lib_ratio 202306L # endif # endif -#endif /* !defined(__cpp_lib_ratio) && defined(__glibcxx_want_ratio) */ +#endif /* !defined(__cpp_lib_ratio) */ #undef __glibcxx_want_ratio #if !defined(__cpp_lib_reference_wrapper) @@ -2120,7 +2333,7 @@ # define __cpp_lib_reference_wrapper 202403L # endif # endif -#endif /* !defined(__cpp_lib_reference_wrapper) && defined(__glibcxx_want_reference_wrapper) */ +#endif /* !defined(__cpp_lib_reference_wrapper) */ #undef __glibcxx_want_reference_wrapper #if !defined(__cpp_lib_saturation_arithmetic) @@ -2130,7 +2343,7 @@ # define __cpp_lib_saturation_arithmetic 202311L # endif # endif -#endif /* !defined(__cpp_lib_saturation_arithmetic) && defined(__glibcxx_want_saturation_arithmetic) */ +#endif /* !defined(__cpp_lib_saturation_arithmetic) */ #undef __glibcxx_want_saturation_arithmetic #if !defined(__cpp_lib_span_initializer_list) @@ -2140,7 +2353,7 @@ # define __cpp_lib_span_initializer_list 202311L # endif # endif -#endif /* !defined(__cpp_lib_span_initializer_list) && defined(__glibcxx_want_span_initializer_list) */ +#endif /* !defined(__cpp_lib_span_initializer_list) */ #undef __glibcxx_want_span_initializer_list #if !defined(__cpp_lib_text_encoding) @@ -2150,7 +2363,7 @@ # define __cpp_lib_text_encoding 202306L # endif # endif -#endif /* !defined(__cpp_lib_text_encoding) && defined(__glibcxx_want_text_encoding) */ +#endif /* !defined(__cpp_lib_text_encoding) */ #undef __glibcxx_want_text_encoding #if !defined(__cpp_lib_ranges_to_input) @@ -2160,7 +2373,7 @@ # define __cpp_lib_ranges_to_input 202502L # endif # endif -#endif /* !defined(__cpp_lib_ranges_to_input) && defined(__glibcxx_want_ranges_to_input) */ +#endif /* !defined(__cpp_lib_ranges_to_input) */ #undef __glibcxx_want_ranges_to_input #if !defined(__cpp_lib_to_string) @@ -2170,7 +2383,7 @@ # define __cpp_lib_to_string 202306L # endif # endif -#endif /* !defined(__cpp_lib_to_string) && defined(__glibcxx_want_to_string) */ +#endif /* !defined(__cpp_lib_to_string) */ #undef __glibcxx_want_to_string #if !defined(__cpp_lib_modules) @@ -2180,7 +2393,116 @@ # define __cpp_lib_modules 202207L # endif # endif -#endif /* !defined(__cpp_lib_modules) && defined(__glibcxx_want_modules) */ +#endif /* !defined(__cpp_lib_modules) */ #undef __glibcxx_want_modules +#if !defined(__cpp_lib_inplace_vector) +# if (__cplusplus > 202302L) +# define __glibcxx_inplace_vector 202406L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_inplace_vector) +# define __cpp_lib_inplace_vector 202406L +# endif +# endif +#endif /* !defined(__cpp_lib_inplace_vector) */ +#undef __glibcxx_want_inplace_vector + +#if !defined(__cpp_lib_indirect) +# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED +# define __glibcxx_indirect 202502L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_indirect) +# define __cpp_lib_indirect 202502L +# endif +# endif +#endif /* !defined(__cpp_lib_indirect) */ +#undef __glibcxx_want_indirect + +#if !defined(__cpp_lib_polymorphic) +# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED +# define __glibcxx_polymorphic 202502L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_polymorphic) +# define __cpp_lib_polymorphic 202502L +# endif +# endif +#endif /* !defined(__cpp_lib_polymorphic) */ +#undef __glibcxx_want_polymorphic + +#if !defined(__cpp_lib_smart_ptr_owner_equality) +# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED +# define __glibcxx_smart_ptr_owner_equality 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_smart_ptr_owner_equality) +# define __cpp_lib_smart_ptr_owner_equality 202306L +# endif +# endif +#endif /* !defined(__cpp_lib_smart_ptr_owner_equality) */ +#undef __glibcxx_want_smart_ptr_owner_equality + +#if !defined(__cpp_lib_sstream_from_string_view) +# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED +# define __glibcxx_sstream_from_string_view 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_sstream_from_string_view) +# define __cpp_lib_sstream_from_string_view 202306L +# endif +# endif +#endif /* !defined(__cpp_lib_sstream_from_string_view) */ +#undef __glibcxx_want_sstream_from_string_view + +#if !defined(__cpp_lib_type_order) +# if (__cplusplus > 202302L) && (__has_builtin(__builtin_type_order) && __cpp_lib_three_way_comparison >= 201907L) +# define __glibcxx_type_order 202506L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_type_order) +# define __cpp_lib_type_order 202506L +# endif +# endif +#endif /* !defined(__cpp_lib_type_order) */ +#undef __glibcxx_want_type_order + +#if !defined(__cpp_lib_exception_ptr_cast) +# if (__cplusplus > 202302L) +# define __glibcxx_exception_ptr_cast 202506L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_exception_ptr_cast) +# define __cpp_lib_exception_ptr_cast 202506L +# endif +# endif +#endif /* !defined(__cpp_lib_exception_ptr_cast) */ +#undef __glibcxx_want_exception_ptr_cast + +#if !defined(__cpp_lib_bitset) +# if (__cplusplus > 202302L) +# define __glibcxx_bitset 202306L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_bitset) +# define __cpp_lib_bitset 202306L +# endif +# endif +#endif /* !defined(__cpp_lib_bitset) */ +#undef __glibcxx_want_bitset + +#if !defined(__cpp_lib_constexpr_exceptions) +# if (__cplusplus > 202302L) && (__cpp_constexpr_exceptions >= 202411L) +# define __glibcxx_constexpr_exceptions 1L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_constexpr_exceptions) +# endif +# endif +#endif /* !defined(__cpp_lib_constexpr_exceptions) */ +#undef __glibcxx_want_constexpr_exceptions + +#if !defined(__cpp_lib_philox_engine) +# if (__cplusplus > 202302L) && (__SIZEOF_INT128__) +# define __glibcxx_philox_engine 202406L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_philox_engine) +# define __cpp_lib_philox_engine 202406L +# endif +# endif +#endif /* !defined(__cpp_lib_philox_engine) */ +#undef __glibcxx_want_philox_engine + +#if !defined(__cpp_lib_is_implicit_lifetime) +# if (__cplusplus >= 202100L) && (__has_builtin(__builtin_is_implicit_lifetime)) +# define __glibcxx_is_implicit_lifetime 202302L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_implicit_lifetime) +# define __cpp_lib_is_implicit_lifetime 202302L +# endif +# endif +#endif /* !defined(__cpp_lib_is_implicit_lifetime) */ +#undef __glibcxx_want_is_implicit_lifetime + #undef __glibcxx_want_all diff --git a/libstdc++-v3/include/bits/version.tpl b/libstdc++-v3/include/bits/version.tpl index ccda71d..5d62b2a 100644 --- a/libstdc++-v3/include/bits/version.tpl +++ b/libstdc++-v3/include/bits/version.tpl @@ -132,10 +132,11 @@ h This macro block defines two versions of each FTM: - 1. __glibcxx_NAME, which is defined unconditionally, and - 2. __cpp_lib_NAME, which is defined only if marked as wanted. + 1. __glibcxx_NAME, which is defined as long its conditions are met, and + 2. __cpp_lib_NAME, which is defined only if __glibcxx_want_NAME is defined + and no_stdname is not set. - This allows FTMs to depend on eachother in their definitions without messing + This allows FTMs to depend on each other in their definitions without messing with the exported values. This can also be used by bits that do not want to expose FTMs that they can't @@ -155,7 +156,7 @@ h # endif /*{ ENDFOR values }*/# endif -#endif /* !defined(__cpp_lib_/*{name}*/) && defined(__glibcxx_want_/*{name}*/) */ +#endif /* !defined(__cpp_lib_/*{name}*/) */ #undef __glibcxx_want_/*{name }*//*{ (unless (last-for?) "\n\n" "\n")}*/ /*{ ENDFOR ftms }*//*{ |
