diff options
Diffstat (limited to 'libstdc++-v3/include/std')
-rw-r--r-- | libstdc++-v3/include/std/algorithm | 1 | ||||
-rw-r--r-- | libstdc++-v3/include/std/barrier | 199 | ||||
-rw-r--r-- | libstdc++-v3/include/std/bit | 4 | ||||
-rw-r--r-- | libstdc++-v3/include/std/bitset | 82 | ||||
-rw-r--r-- | libstdc++-v3/include/std/chrono | 24 | ||||
-rw-r--r-- | libstdc++-v3/include/std/complex | 26 | ||||
-rw-r--r-- | libstdc++-v3/include/std/flat_map | 16 | ||||
-rw-r--r-- | libstdc++-v3/include/std/format | 520 | ||||
-rw-r--r-- | libstdc++-v3/include/std/functional | 32 | ||||
-rw-r--r-- | libstdc++-v3/include/std/latch | 26 | ||||
-rw-r--r-- | libstdc++-v3/include/std/mdspan | 762 | ||||
-rw-r--r-- | libstdc++-v3/include/std/memory | 6 | ||||
-rw-r--r-- | libstdc++-v3/include/std/optional | 47 | ||||
-rw-r--r-- | libstdc++-v3/include/std/ranges | 48 | ||||
-rw-r--r-- | libstdc++-v3/include/std/semaphore | 31 | ||||
-rw-r--r-- | libstdc++-v3/include/std/sstream | 202 | ||||
-rw-r--r-- | libstdc++-v3/include/std/stop_token | 7 | ||||
-rw-r--r-- | libstdc++-v3/include/std/tuple | 24 | ||||
-rw-r--r-- | libstdc++-v3/include/std/type_traits | 106 | ||||
-rw-r--r-- | libstdc++-v3/include/std/utility | 2 |
20 files changed, 1677 insertions, 488 deletions
diff --git a/libstdc++-v3/include/std/algorithm b/libstdc++-v3/include/std/algorithm index 321a5e2..1563cdf 100644 --- a/libstdc++-v3/include/std/algorithm +++ b/libstdc++-v3/include/std/algorithm @@ -74,6 +74,7 @@ #define __glibcxx_want_ranges_contains #define __glibcxx_want_ranges_find_last #define __glibcxx_want_ranges_fold +#define __glibcxx_want_ranges_starts_ends_with #define __glibcxx_want_robust_nonmodifying_seq_ops #define __glibcxx_want_sample #define __glibcxx_want_shift diff --git a/libstdc++-v3/include/std/barrier b/libstdc++-v3/include/std/barrier index 6c3cfd4..56270c9 100644 --- a/libstdc++-v3/include/std/barrier +++ b/libstdc++-v3/include/std/barrier @@ -81,105 +81,142 @@ It looks different from literature pseudocode for two main reasons: enum class __barrier_phase_t : unsigned char { }; - template<typename _CompletionF> - class __tree_barrier + struct __tree_barrier_base + { + static constexpr ptrdiff_t + max() noexcept + { return __PTRDIFF_MAX__ - 1; } + + protected: + using __atomic_phase_ref_t = std::__atomic_ref<__barrier_phase_t>; + using __atomic_phase_const_ref_t = std::__atomic_ref<const __barrier_phase_t>; + static constexpr auto __phase_alignment = + __atomic_phase_ref_t::required_alignment; + + using __tickets_t = std::array<__barrier_phase_t, 64>; + struct alignas(64) /* naturally-align the heap state */ __state_t { - using __atomic_phase_ref_t = std::__atomic_ref<__barrier_phase_t>; - using __atomic_phase_const_ref_t = std::__atomic_ref<const __barrier_phase_t>; - static constexpr auto __phase_alignment = - __atomic_phase_ref_t::required_alignment; + alignas(__phase_alignment) __tickets_t __tickets; + }; - using __tickets_t = std::array<__barrier_phase_t, 64>; - struct alignas(64) /* naturally-align the heap state */ __state_t - { - alignas(__phase_alignment) __tickets_t __tickets; - }; + ptrdiff_t _M_expected; + __atomic_base<__state_t*> _M_state{nullptr}; + __atomic_base<ptrdiff_t> _M_expected_adjustment{0}; + alignas(__phase_alignment) __barrier_phase_t _M_phase{}; - ptrdiff_t _M_expected; - unique_ptr<__state_t[]> _M_state; - __atomic_base<ptrdiff_t> _M_expected_adjustment; - _CompletionF _M_completion; + explicit constexpr + __tree_barrier_base(ptrdiff_t __expected) + : _M_expected(__expected) + { + __glibcxx_assert(__expected >= 0 && __expected <= max()); - alignas(__phase_alignment) __barrier_phase_t _M_phase; + if (!std::is_constant_evaluated()) + _M_state.store(_M_alloc_state().release(), memory_order_release); + } - bool - _M_arrive(__barrier_phase_t __old_phase, size_t __current) - { - const auto __old_phase_val = static_cast<unsigned char>(__old_phase); - const auto __half_step = - static_cast<__barrier_phase_t>(__old_phase_val + 1); - const auto __full_step = - static_cast<__barrier_phase_t>(__old_phase_val + 2); + unique_ptr<__state_t[]> + _M_alloc_state() + { + size_t const __count = (_M_expected + 1) >> 1; + return std::make_unique<__state_t[]>(__count); + } - size_t __current_expected = _M_expected; - __current %= ((_M_expected + 1) >> 1); + bool + _M_arrive(__barrier_phase_t __old_phase, size_t __current) + { + const auto __old_phase_val = static_cast<unsigned char>(__old_phase); + const auto __half_step = + static_cast<__barrier_phase_t>(__old_phase_val + 1); + const auto __full_step = + static_cast<__barrier_phase_t>(__old_phase_val + 2); + + size_t __current_expected = _M_expected; + __current %= ((_M_expected + 1) >> 1); + + __state_t* const __state = _M_state.load(memory_order_relaxed); + + for (int __round = 0; ; ++__round) + { + if (__current_expected <= 1) + return true; + size_t const __end_node = ((__current_expected + 1) >> 1), + __last_node = __end_node - 1; + for ( ; ; ++__current) + { + if (__current == __end_node) + __current = 0; + auto __expect = __old_phase; + __atomic_phase_ref_t __phase(__state[__current] + .__tickets[__round]); + if (__current == __last_node && (__current_expected & 1)) + { + if (__phase.compare_exchange_strong(__expect, __full_step, + memory_order_acq_rel)) + break; // I'm 1 in 1, go to next __round + } + else if (__phase.compare_exchange_strong(__expect, __half_step, + memory_order_acq_rel)) + { + return false; // I'm 1 in 2, done with arrival + } + else if (__expect == __half_step) + { + if (__phase.compare_exchange_strong(__expect, __full_step, + memory_order_acq_rel)) + break; // I'm 2 in 2, go to next __round + } + } + __current_expected = __last_node + 1; + __current >>= 1; + } + } + }; - for (int __round = 0; ; ++__round) - { - if (__current_expected <= 1) - return true; - size_t const __end_node = ((__current_expected + 1) >> 1), - __last_node = __end_node - 1; - for ( ; ; ++__current) - { - if (__current == __end_node) - __current = 0; - auto __expect = __old_phase; - __atomic_phase_ref_t __phase(_M_state[__current] - .__tickets[__round]); - if (__current == __last_node && (__current_expected & 1)) - { - if (__phase.compare_exchange_strong(__expect, __full_step, - memory_order_acq_rel)) - break; // I'm 1 in 1, go to next __round - } - else if (__phase.compare_exchange_strong(__expect, __half_step, - memory_order_acq_rel)) - { - return false; // I'm 1 in 2, done with arrival - } - else if (__expect == __half_step) - { - if (__phase.compare_exchange_strong(__expect, __full_step, - memory_order_acq_rel)) - break; // I'm 2 in 2, go to next __round - } - } - __current_expected = __last_node + 1; - __current >>= 1; - } - } + template<typename _CompletionF> + class __tree_barrier : public __tree_barrier_base + { + [[no_unique_address]] _CompletionF _M_completion; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3898. Possibly unintended preconditions for completion functions + void _M_invoke_completion() noexcept { _M_completion(); } public: using arrival_token = __barrier_phase_t; - static constexpr ptrdiff_t - max() noexcept - { return __PTRDIFF_MAX__; } - + constexpr __tree_barrier(ptrdiff_t __expected, _CompletionF __completion) - : _M_expected(__expected), _M_expected_adjustment(0), - _M_completion(move(__completion)), - _M_phase(static_cast<__barrier_phase_t>(0)) - { - size_t const __count = (_M_expected + 1) >> 1; - - _M_state = std::make_unique<__state_t[]>(__count); - } + : __tree_barrier_base(__expected), _M_completion(std::move(__completion)) + { } [[nodiscard]] arrival_token arrive(ptrdiff_t __update) { + __glibcxx_assert(__update > 0); + // FIXME: Check that update is less than or equal to the expected count + // for the current barrier phase. + std::hash<std::thread::id> __hasher; size_t __current = __hasher(std::this_thread::get_id()); __atomic_phase_ref_t __phase(_M_phase); const auto __old_phase = __phase.load(memory_order_relaxed); const auto __cur = static_cast<unsigned char>(__old_phase); - for(; __update; --__update) + + if (__cur == 0 && !_M_state.load(memory_order_relaxed)) [[unlikely]] + { + auto __p = _M_alloc_state(); + __state_t* __val = nullptr; + if (_M_state.compare_exchange_strong(__val, __p.get(), + memory_order_seq_cst, + memory_order_acquire)) + __p.release(); + } + + for (; __update; --__update) { - if(_M_arrive(__old_phase, __current)) + if (_M_arrive(__old_phase, __current)) { - _M_completion(); + _M_invoke_completion(); _M_expected += _M_expected_adjustment.load(memory_order_relaxed); _M_expected_adjustment.store(0, memory_order_relaxed); auto __new_phase = static_cast<__barrier_phase_t>(__cur + 2); @@ -194,11 +231,7 @@ It looks different from literature pseudocode for two main reasons: wait(arrival_token&& __old_phase) const { __atomic_phase_const_ref_t __phase(_M_phase); - auto const __test_fn = [=] - { - return __phase.load(memory_order_acquire) != __old_phase; - }; - std::__atomic_wait_address(&_M_phase, __test_fn); + __phase.wait(__old_phase, memory_order_acquire); } void @@ -212,6 +245,8 @@ It looks different from literature pseudocode for two main reasons: template<typename _CompletionF = __empty_completion> class barrier { + static_assert(is_invocable_v<_CompletionF&>); + // Note, we may introduce a "central" barrier algorithm at some point // for more space constrained targets using __algorithm_t = __tree_barrier<_CompletionF>; @@ -236,7 +271,7 @@ It looks different from literature pseudocode for two main reasons: max() noexcept { return __algorithm_t::max(); } - explicit + constexpr explicit barrier(ptrdiff_t __count, _CompletionF __completion = _CompletionF()) : _M_b(__count, std::move(__completion)) { } diff --git a/libstdc++-v3/include/std/bit b/libstdc++-v3/include/std/bit index 5187c96..fd75edf 100644 --- a/libstdc++-v3/include/std/bit +++ b/libstdc++-v3/include/std/bit @@ -166,7 +166,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Variant for power of two _Nd which the compiler can // easily pattern match. constexpr unsigned __uNd = _Nd; - const unsigned __r = __s; + const auto __r = static_cast<unsigned>(__s); return (__x << (__r % __uNd)) | (__x >> ((-__r) % __uNd)); } const int __r = __s % _Nd; @@ -188,7 +188,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Variant for power of two _Nd which the compiler can // easily pattern match. constexpr unsigned __uNd = _Nd; - const unsigned __r = __s; + const auto __r = static_cast<unsigned>(__s); return (__x >> (__r % __uNd)) | (__x << ((-__r) % __uNd)); } const int __r = __s % _Nd; diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset index 8b5d270..1c1e167 100644 --- a/libstdc++-v3/include/std/bitset +++ b/libstdc++-v3/include/std/bitset @@ -61,8 +61,13 @@ #endif #define __glibcxx_want_constexpr_bitset +#define __glibcxx_want_bitset // ...construct from string_view #include <bits/version.h> +#ifdef __cpp_lib_bitset // ...construct from string_view +# include <string_view> +#endif + #define _GLIBCXX_BITSET_BITS_PER_WORD (__CHAR_BIT__ * __SIZEOF_LONG__) #define _GLIBCXX_BITSET_WORDS(__n) \ ((__n) / _GLIBCXX_BITSET_BITS_PER_WORD + \ @@ -752,7 +757,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER * (Note that %bitset does @e not meet the formal requirements of a * <a href="tables.html#65">container</a>. Mainly, it lacks iterators.) * - * The template argument, @a Nb, may be any non-negative number, + * The template argument, `Nb`, may be any non-negative number, * specifying the number of bits (e.g., "0", "12", "1024*1024"). * * In the general unoptimized case, storage is allocated in word-sized @@ -816,28 +821,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)> _Base; typedef unsigned long _WordT; -#if _GLIBCXX_HOSTED - template<class _CharT, class _Traits, class _Alloc> - _GLIBCXX23_CONSTEXPR - void - _M_check_initial_position(const std::basic_string<_CharT, _Traits, _Alloc>& __s, - size_t __position) const + template<class _Str> + _GLIBCXX23_CONSTEXPR void + _M_check_initial_position( + const _Str& __s, typename _Str::size_type __position) const { if (__position > __s.size()) - __throw_out_of_range_fmt(__N("bitset::bitset: __position " - "(which is %zu) > __s.size() " - "(which is %zu)"), - __position, __s.size()); + __throw_out_of_range_fmt( + __N("bitset::bitset:" + " __position (which is %zu) > __s.size() (which is %zu)"), + size_t(__position), size_t(__s.size())); } -#endif // HOSTED _GLIBCXX23_CONSTEXPR void _M_check(size_t __position, const char *__s) const { if (__position >= _Nb) - __throw_out_of_range_fmt(__N("%s: __position (which is %zu) " - ">= _Nb (which is %zu)"), - __s, __position, _Nb); + __throw_out_of_range_fmt( + __N("%s: __position (which is %zu) >= _Nb (which is %zu)"), + __s, size_t(__position), size_t(_Nb)); } _GLIBCXX23_CONSTEXPR @@ -954,12 +956,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #if _GLIBCXX_HOSTED /** * Use a subset of a string. - * @param __s A string of @a 0 and @a 1 characters. - * @param __position Index of the first character in @a __s to use; + * @param __s A string of `0` and `1` characters. + * @param __position Index of the first character in `__s` to use; * defaults to zero. - * @throw std::out_of_range If @a pos is bigger the size of @a __s. + * @throw std::out_of_range If `__position > __s.size()`. * @throw std::invalid_argument If a character appears in the string - * which is neither @a 0 nor @a 1. + * which is neither `0` nor `1`. */ template<class _CharT, class _Traits, class _Alloc> _GLIBCXX23_CONSTEXPR @@ -976,13 +978,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER /** * Use a subset of a string. - * @param __s A string of @a 0 and @a 1 characters. - * @param __position Index of the first character in @a __s to use. + * @param __s A string of `0` and `1` characters. + * @param __position Index of the first character in `__s` to use. * @param __n The number of characters to copy. - * @throw std::out_of_range If @a __position is bigger the size - * of @a __s. + * @throw std::out_of_range If `__position > __s.size()`. * @throw std::invalid_argument If a character appears in the string - * which is neither @a 0 nor @a 1. + * which is neither `0` nor `1`. */ template<class _CharT, class _Traits, class _Alloc> _GLIBCXX23_CONSTEXPR @@ -1008,15 +1009,42 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } #endif // HOSTED +#ifdef __cpp_lib_bitset + /** + * Use a subset of a string view. + * @param __s A `string_view` of a sequence of `0` and `1` characters. + * @param __position Index of the first character in `__s` to use. + * @param __n The maximum number of characters from `__s` to use. + * @param __zero The character corresponding to the value 0. + * @param __one The character corresponding to the value 1. + * @throw std::out_of_range If `__position > __s.size()`. + * @throw std::invalid_argument If a character appears in `__s` + * which is neither `0` nor `1`. + */ + template<class _CharT, class _Traits> + constexpr explicit + bitset(basic_string_view<_CharT, _Traits> __s, + basic_string_view<_CharT, _Traits>::size_type __position = 0, + basic_string_view<_CharT, _Traits>::size_type __n = + basic_string_view<_CharT, _Traits>::npos, + _CharT __zero = _CharT('0'), _CharT __one = _CharT('1')) + : _Base() + { + _M_check_initial_position(__s, __position); + _M_copy_from_ptr<_CharT, _Traits>( + __s.data(), __s.size(), __position, __n, __zero, __one); + } +#endif + #if __cplusplus >= 201103L /** * Construct from a character %array. - * @param __str An %array of characters @a zero and @a one. + * @param __str An %array of characters `__zero` and `__one`. * @param __n The number of characters to use. * @param __zero The character corresponding to the value 0. * @param __one The character corresponding to the value 1. * @throw std::invalid_argument If a character appears in the string - * which is neither @a __zero nor @a __one. + * which is neither `__zero` nor `__one`. */ template<typename _CharT> [[__gnu__::__nonnull__]] @@ -1028,10 +1056,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _CharT __zero = _CharT('0'), _CharT __one = _CharT('1')) : _Base() { -#if _GLIBCXX_HOSTED if (!__str) __throw_logic_error(__N("bitset::bitset(const _CharT*, ...)")); -#endif using _Traits = typename __bitset::__string<_CharT>::traits_type; if (__n == __bitset::__string<_CharT>::npos) diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono index 8eb9fd9..cb8213e 100644 --- a/libstdc++-v3/include/std/chrono +++ b/libstdc++-v3/include/std/chrono @@ -2305,8 +2305,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __r *= 10; return __r; } - - template<typename _Duration> struct __utc_leap_second; } /// @endcond @@ -2481,30 +2479,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __byte_duration<ratio<1>> _M_s{}; bool _M_is_neg{}; __subseconds<precision> _M_ss{}; - - template<typename> friend struct __detail::__utc_leap_second; }; - /// @cond undocumented - namespace __detail - { - // Represents a time that is within a leap second insertion. - template<typename _Duration> - struct __utc_leap_second - { - explicit - __utc_leap_second(const sys_time<_Duration>& __s) - : _M_date(chrono::floor<days>(__s)), _M_time(__s - _M_date) - { - ++_M_time._M_s; - } - - sys_days _M_date; - hh_mm_ss<common_type_t<_Duration, days>> _M_time; - }; - } - /// @endcond - // 12/24 HOURS FUNCTIONS constexpr bool diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex index 59ef905..d9d2d8a 100644 --- a/libstdc++-v3/include/std/complex +++ b/libstdc++-v3/include/std/complex @@ -969,7 +969,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif - // 26.2.7/4: arg(__z): Returns the phase angle of __z. + // C++11 26.4.7 [complex.value.ops]/4: arg(z): Returns the phase angle of z. template<typename _Tp> inline _Tp __complex_arg(const complex<_Tp>& __z) @@ -2123,8 +2123,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> std::complex<_Tp> acosh(const std::complex<_Tp>&); template<typename _Tp> std::complex<_Tp> asinh(const std::complex<_Tp>&); template<typename _Tp> std::complex<_Tp> atanh(const std::complex<_Tp>&); - // DR 595. - template<typename _Tp> _Tp fabs(const std::complex<_Tp>&); template<typename _Tp> inline std::complex<_Tp> @@ -2309,7 +2307,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION acos(const std::complex<_Tp>& __z) { return __complex_acos(__z.__rep()); } #else - /// acos(__z) [8.1.2]. + /// acos(__z) C++11 26.4.8 [complex.transcendentals] // Effects: Behaves the same as C99 function cacos, defined // in subclause 7.3.5.1. template<typename _Tp> @@ -2345,7 +2343,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION asin(const std::complex<_Tp>& __z) { return __complex_asin(__z.__rep()); } #else - /// asin(__z) [8.1.3]. + /// asin(__z) C++11 26.4.8 [complex.transcendentals] // Effects: Behaves the same as C99 function casin, defined // in subclause 7.3.5.2. template<typename _Tp> @@ -2389,7 +2387,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION atan(const std::complex<_Tp>& __z) { return __complex_atan(__z.__rep()); } #else - /// atan(__z) [8.1.4]. + /// atan(__z) C++11 26.4.8 [complex.transcendentals] // Effects: Behaves the same as C99 function catan, defined // in subclause 7.3.5.3. template<typename _Tp> @@ -2425,7 +2423,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION acosh(const std::complex<_Tp>& __z) { return __complex_acosh(__z.__rep()); } #else - /// acosh(__z) [8.1.5]. + /// acosh(__z) C++11 26.4.8 [complex.transcendentals] // Effects: Behaves the same as C99 function cacosh, defined // in subclause 7.3.6.1. template<typename _Tp> @@ -2464,7 +2462,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION asinh(const std::complex<_Tp>& __z) { return __complex_asinh(__z.__rep()); } #else - /// asinh(__z) [8.1.6]. + /// asinh(__z) C++11 26.4.8 [complex.transcendentals] // Effects: Behaves the same as C99 function casin, defined // in subclause 7.3.6.2. template<typename _Tp> @@ -2508,7 +2506,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION atanh(const std::complex<_Tp>& __z) { return __complex_atanh(__z.__rep()); } #else - /// atanh(__z) [8.1.7]. + /// atanh(__z) C++11 26.4.8 [complex.transcendentals] // Effects: Behaves the same as C99 function catanh, defined // in subclause 7.3.6.3. template<typename _Tp> @@ -2518,22 +2516,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif template<typename _Tp> + _GLIBCXX11_DEPRECATED_SUGGEST("std::abs") inline _Tp - /// fabs(__z) [8.1.8]. + /// fabs(__z) TR1 8.1.8 [tr.c99.cmplx.fabs] // Effects: Behaves the same as C99 function cabs, defined // in subclause 7.3.8.1. fabs(const std::complex<_Tp>& __z) { return std::abs(__z); } - /// Additional overloads [8.1.9]. + // Additional overloads C++11 26.4.9 [cmplx.over] + template<typename _Tp> inline typename __gnu_cxx::__promote<_Tp>::__type arg(_Tp __x) { typedef typename __gnu_cxx::__promote<_Tp>::__type __type; #if (_GLIBCXX11_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC) - return std::signbit(__x) ? __type(3.1415926535897932384626433832795029L) - : __type(); + return __builtin_signbit(__type(__x)) + ? __type(3.1415926535897932384626433832795029L) : __type(); #else return std::arg(std::complex<__type>(__x)); #endif diff --git a/libstdc++-v3/include/std/flat_map b/libstdc++-v3/include/std/flat_map index 6593988..de006ad 100644 --- a/libstdc++-v3/include/std/flat_map +++ b/libstdc++-v3/include/std/flat_map @@ -873,7 +873,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION [[nodiscard]] friend bool operator==(const _Derived& __x, const _Derived& __y) - { return std::equal(__x.begin(), __x.end(), __y.begin(), __y.end()); } + { + return __x._M_cont.keys == __y._M_cont.keys + && __x._M_cont.values == __y._M_cont.values; + } template<typename _Up = value_type> [[nodiscard]] @@ -895,7 +898,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { auto __guard = _M_make_clear_guard(); auto __zv = views::zip(_M_cont.keys, _M_cont.values); - auto __sr = ranges::remove_if(__zv, __pred); + auto __sr = ranges::remove_if(__zv, __pred, + [](const auto& __e) { + return const_reference(__e); + }); auto __erased = __sr.size(); erase(end() - __erased, end()); __guard._M_disable(); @@ -1142,14 +1148,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // element access mapped_type& operator[](const key_type& __x) - { return operator[]<const key_type>(__x); } + { return try_emplace(__x).first->second; } mapped_type& operator[](key_type&& __x) - { return operator[]<key_type>(std::move(__x)); } + { return try_emplace(std::move(__x)).first->second; } template<typename _Key2> - requires same_as<remove_cvref_t<_Key2>, _Key> || __transparent_comparator<_Compare> + requires __transparent_comparator<_Compare> mapped_type& operator[](_Key2&& __x) { return try_emplace(std::forward<_Key2>(__x)).first->second; } diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index b3192cf..46bd5d5 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -472,30 +472,33 @@ namespace __format return {0, nullptr}; } - enum _Pres_type { + enum class _Pres_type : unsigned char { _Pres_none = 0, // Default type (not valid for integer presentation types). + _Pres_s = 1, // For strings, bool, ranges // Presentation types for integral types (including bool and charT). - _Pres_d = 1, _Pres_b, _Pres_B, _Pres_o, _Pres_x, _Pres_X, _Pres_c, - // Presentation types for floating-point types. - _Pres_a = 1, _Pres_A, _Pres_e, _Pres_E, _Pres_f, _Pres_F, _Pres_g, _Pres_G, - _Pres_p = 0, _Pres_P, // For pointers. - _Pres_s = 0, // For strings, bool - _Pres_seq = 0, _Pres_str, // For ranges - _Pres_esc = 0xf, // For strings, charT and ranges + _Pres_c = 2, _Pres_x, _Pres_X, _Pres_d, _Pres_o, _Pres_b, _Pres_B, + // Presentation types for floating-point types + _Pres_g = 1, _Pres_G, _Pres_a, _Pres_A, _Pres_e, _Pres_E, _Pres_f, _Pres_F, + // For pointers, the value are same as hexadecimal presentations for integers + _Pres_p = _Pres_x, _Pres_P = _Pres_X, + _Pres_max = 0xf, }; + using enum _Pres_type; - enum _Sign { + enum class _Sign : unsigned char { _Sign_default, _Sign_plus, _Sign_minus, // XXX does this need to be distinct from _Sign_default? _Sign_space, }; + using enum _Sign; - enum _WidthPrec { + enum _WidthPrec : unsigned char { _WP_none, // No width/prec specified. _WP_value, // Fixed width/prec specified. _WP_from_arg // Use a formatting argument for width/prec. }; + using enum _WidthPrec; template<typename _Context> size_t @@ -507,9 +510,17 @@ namespace __format constexpr bool __is_xdigit(char __c) { return std::__detail::__from_chars_alnum_to_val(__c) < 16; } + // Used to make _Spec a non-C++98 POD, so the tail-padding is used. + // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#pod + struct _SpecBase + { }; + template<typename _CharT> - struct _Spec + struct _Spec : _SpecBase { + unsigned short _M_width; + unsigned short _M_prec; + char32_t _M_fill = ' '; _Align _M_align : 2; _Sign _M_sign : 2; unsigned _M_alt : 1; @@ -517,12 +528,11 @@ namespace __format unsigned _M_zero_fill : 1; _WidthPrec _M_width_kind : 2; _WidthPrec _M_prec_kind : 2; + unsigned _M_debug : 1; _Pres_type _M_type : 4; - unsigned _M_reserved : 1; - unsigned _M_reserved2 : 16; - unsigned short _M_width; - unsigned short _M_prec; - char32_t _M_fill = ' '; + unsigned _M_reserved : 8; + // This class has 8 bits of tail padding, that can be used by + // derived classes. using iterator = typename basic_string_view<_CharT>::iterator; @@ -562,7 +572,7 @@ namespace __format char32_t __c = *__beg++; if (__is_scalar_value(__c)) if (auto __next = __beg.base(); __next != __last) - if (_Align __align = _S_align(*__next)) + if (_Align __align = _S_align(*__next); __align != _Align_default) { _M_fill = __c; _M_align = __align; @@ -571,14 +581,14 @@ namespace __format } } else if (__last - __first >= 2) - if (_Align __align = _S_align(__first[1])) + if (_Align __align = _S_align(__first[1]); __align != _Align_default) { _M_fill = *__first; _M_align = __align; return __first + 2; } - if (_Align __align = _S_align(__first[0])) + if (_Align __align = _S_align(__first[0]); __align != _Align_default) { _M_fill = ' '; _M_align = __align; @@ -603,7 +613,7 @@ namespace __format constexpr iterator _M_parse_sign(iterator __first, iterator) noexcept { - if (_Sign __sign = _S_sign(*__first)) + if (_Sign __sign = _S_sign(*__first); __sign != _Sign_default) { _M_sign = __sign; return __first + 1; @@ -871,7 +881,7 @@ namespace __format const size_t __nfill = __width - __estimated_width; - if (__spec._M_align) + if (__spec._M_align != _Align_default) __align = __spec._M_align; return __format::__write_padded(__fc.out(), __str, __align, __nfill, @@ -896,12 +906,12 @@ namespace __format } } - - // Values are indices into _Escapes::all. enum class _Term_char : unsigned char { - _Tc_quote = 12, - _Tc_apos = 15 + _Term_none, + _Term_quote, + _Term_apos, }; + using enum _Term_char; template<typename _CharT> struct _Escapes @@ -912,10 +922,6 @@ namespace __format _Str_view _S_all() { return _GLIBCXX_WIDEN("\t\\t\n\\n\r\\r\\\\\\\"\\\"'\\'\\u\\x"); } - static constexpr - _CharT _S_term(_Term_char __term) - { return _S_all()[static_cast<unsigned char>(__term)]; } - static consteval _Str_view _S_tab() { return _S_all().substr(0, 3); } @@ -947,6 +953,21 @@ namespace __format static consteval _Str_view _S_x() { return _S_all().substr(20, 2); } + + static constexpr + _Str_view _S_term(_Term_char __term) + { + switch (__term) + { + case _Term_none: + return _Str_view(); + case _Term_quote: + return _S_quote().substr(0, 1); + case _Term_apos: + return _S_apos().substr(0, 1); + } + __builtin_unreachable(); + } }; template<typename _CharT> @@ -991,9 +1012,9 @@ namespace __format case _Esc::_S_bslash()[0]: return true; case _Esc::_S_quote()[0]: - return __term == _Term_char::_Tc_quote; + return __term == _Term_quote; case _Esc::_S_apos()[0]: - return __term == _Term_char::_Tc_apos; + return __term == _Term_apos; default: return (__c >= 0 && __c < 0x20) || __c == 0x7f; }; @@ -1062,9 +1083,8 @@ namespace __format case _Esc::_S_apos()[0]: return __format::__write(__out, _Esc::_S_apos().substr(1, 2)); default: - return __format::__write_escape_seq(__out, - static_cast<_UChar>(__c), - _Esc::_S_u()); + return __format::__write_escape_seq( + __out, static_cast<_UChar>(__c), _Esc::_S_u()); } } @@ -1177,8 +1197,7 @@ namespace __format _Out __write_escaped(_Out __out, basic_string_view<_CharT> __str, _Term_char __term) { - *__out = _Escapes<_CharT>::_S_term(__term); - ++__out; + __out = __format::__write(__out, _Escapes<_CharT>::_S_term(__term)); if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>()) __out = __format::__write_escaped_unicode(__out, __str, __term); @@ -1189,8 +1208,7 @@ namespace __format // TODO Handle non-ascii extended encoding __out = __format::__write_escaped_ascii(__out, __str, __term); - *__out = _Escapes<_CharT>::_S_term(__term); - return ++__out; + return __format::__write(__out, _Escapes<_CharT>::_S_term(__term)); } // A lightweight optional<locale>. @@ -1312,11 +1330,14 @@ namespace __format return __first; if (*__first == 's') - ++__first; + { + __spec._M_type = _Pres_s; + ++__first; + } #if __glibcxx_format_ranges // C++ >= 23 && HOSTED else if (*__first == '?') { - __spec._M_type = _Pres_esc; + __spec._M_debug = true; ++__first; } #endif @@ -1332,7 +1353,7 @@ namespace __format format(basic_string_view<_CharT> __s, basic_format_context<_Out, _CharT>& __fc) const { - if (_M_spec._M_type == _Pres_esc) + if (_M_spec._M_debug) return _M_format_escaped(__s, __fc); if (_M_spec._M_width_kind == _WP_none @@ -1349,22 +1370,21 @@ namespace __format _M_format_escaped(basic_string_view<_CharT> __s, basic_format_context<_Out, _CharT>& __fc) const { - constexpr auto __term = __format::_Term_char::_Tc_quote; const size_t __padwidth = _M_spec._M_get_width(__fc); if (__padwidth == 0 && _M_spec._M_prec_kind == _WP_none) - return __format::__write_escaped(__fc.out(), __s, __term); + return __format::__write_escaped(__fc.out(), __s, _Term_quote); const size_t __maxwidth = _M_spec._M_get_precision(__fc); const size_t __width = __truncate(__s, __maxwidth); // N.B. Escaping only increases width if (__padwidth <= __width && _M_spec._M_prec_kind == _WP_none) - return __format::__write_escaped(__fc.out(), __s, __term); + return __format::__write_escaped(__fc.out(), __s, _Term_quote); // N.B. [tab:format.type.string] defines '?' as // Copies the escaped string ([format.string.escaped]) to the output, // so precision seem to appy to escaped string. _Padding_sink<_Out, _CharT> __sink(__fc.out(), __padwidth, __maxwidth); - __format::__write_escaped(__sink.out(), __s, __term); + __format::__write_escaped(__sink.out(), __s, _Term_quote); return __sink._M_finish(_M_spec._M_align, _M_spec._M_fill); } @@ -1388,7 +1408,7 @@ namespace __format size_t(ranges::distance(__rg))); return format(__str, __fc); } - else if (_M_spec._M_type != _Pres_esc) + else if (!_M_spec._M_debug) { const size_t __padwidth = _M_spec._M_get_width(__fc); if (__padwidth == 0 && _M_spec._M_prec_kind == _WP_none) @@ -1441,7 +1461,7 @@ namespace __format constexpr void set_debug_format() noexcept - { _M_spec._M_type = _Pres_esc; } + { _M_spec._M_debug = true; } #endif private: @@ -1462,7 +1482,10 @@ namespace __format constexpr __formatter_int(_Spec<_CharT> __spec) noexcept : _M_spec(__spec) - { } + { + if (_M_spec._M_type == _Pres_none) + _M_spec._M_type = _Pres_d; + } constexpr typename basic_format_parse_context<_CharT>::iterator _M_do_parse(basic_format_parse_context<_CharT>& __pc, _Pres_type __type) @@ -1551,7 +1574,7 @@ namespace __format case 's': if (__type == _AsBool) { - __spec._M_type = _Pres_s; // same value (and meaning) as "none" + __spec._M_type = _Pres_s; // same meaning as "none" for bool ++__first; } break; @@ -1559,7 +1582,7 @@ namespace __format case '?': if (__type == _AsChar) { - __spec._M_type = _Pres_esc; + __spec._M_debug = true; ++__first; } #endif @@ -1580,7 +1603,8 @@ namespace __format { auto __end = _M_do_parse(__pc, _AsBool); if (_M_spec._M_type == _Pres_s) - if (_M_spec._M_sign || _M_spec._M_alt || _M_spec._M_zero_fill) + if (_M_spec._M_sign != _Sign_default || _M_spec._M_alt + || _M_spec._M_zero_fill) __throw_format_error("format error: format-spec contains " "invalid formatting options for " "'bool'"); @@ -1589,8 +1613,9 @@ namespace __format else if constexpr (__char<_Tp>) { auto __end = _M_do_parse(__pc, _AsChar); - if (_M_spec._M_type == _Pres_c || _M_spec._M_type == _Pres_esc) - if (_M_spec._M_sign || _M_spec._M_alt || _M_spec._M_zero_fill + if (_M_spec._M_type == _Pres_c) + if (_M_spec._M_sign != _Sign_default || _M_spec._M_alt + || _M_spec._M_zero_fill /* XXX should be invalid? || _M_spec._M_localized */) __throw_format_error("format error: format-spec contains " "invalid formatting options for " @@ -1702,51 +1727,34 @@ namespace __format _M_spec); } - [[__gnu__::__always_inline__]] - static size_t - _S_character_width(_CharT __c) - { - // N.B. single byte cannot encode charcter of width greater than 1 - if constexpr (sizeof(_CharT) > 1u && - __unicode::__literal_encoding_is_unicode<_CharT>()) - return __unicode::__field_width(__c); - else - return 1u; - } - template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator _M_format_character(_CharT __c, - basic_format_context<_Out, _CharT>& __fc) const + basic_format_context<_Out, _CharT>& __fc) const { - return __format::__write_padded_as_spec({&__c, 1u}, - _S_character_width(__c), - __fc, _M_spec); - } + basic_string_view<_CharT> __in(&__c, 1u); + size_t __width = 1u; + // N.B. single byte cannot encode character of width greater than 1 + if constexpr (sizeof(_CharT) > 1u && + __unicode::__literal_encoding_is_unicode<_CharT>()) + __width = __unicode::__field_width(__c); - template<typename _Out> - typename basic_format_context<_Out, _CharT>::iterator - _M_format_character_escaped(_CharT __c, - basic_format_context<_Out, _CharT>& __fc) const - { - using _Esc = _Escapes<_CharT>; - constexpr auto __term = __format::_Term_char::_Tc_apos; - const basic_string_view<_CharT> __in(&__c, 1u); - if (_M_spec._M_get_width(__fc) <= 3u) - return __format::__write_escaped(__fc.out(), __in, __term); + if (!_M_spec._M_debug) + return __format::__write_padded_as_spec(__in, __width, + __fc, _M_spec); + + __width += 2; + if (_M_spec._M_get_width(__fc) <= __width) + return __format::__write_escaped(__fc.out(), __in, _Term_apos); _CharT __buf[12]; - __format::_Fixedbuf_sink<_CharT> __sink(__buf); - __format::__write_escaped(__sink.out(), __in, __term); + _Fixedbuf_sink<_CharT> __sink(__buf); + __format::__write_escaped(__sink.out(), __in, _Term_apos); - const basic_string_view<_CharT> __escaped = __sink.view(); - size_t __estimated_width; - if (__escaped[1] == _Esc::_S_bslash()[0]) // escape sequence - __estimated_width = __escaped.size(); - else - __estimated_width = 2 + _S_character_width(__c); - return __format::__write_padded_as_spec(__escaped, - __estimated_width, + __in = __sink.view(); + if (__in[1] == _Escapes<_CharT>::_S_bslash()[0]) // escape sequence + __width = __in.size(); + return __format::__write_padded_as_spec(__in, __width, __fc, _M_spec); } @@ -1863,20 +1871,24 @@ namespace __format _Spec<_CharT> _M_spec{}; }; +#ifdef __BFLT16_DIG__ + using __bflt16_t = decltype(0.0bf16); +#endif + // Decide how 128-bit floating-point types should be formatted (or not). - // When supported, the typedef __format::__float128_t is the type that - // format arguments should be converted to for storage in basic_format_arg. + // When supported, the typedef __format::__flt128_t is the type that format + // arguments should be converted to before passing them to __formatter_fp. // Define the macro _GLIBCXX_FORMAT_F128 to say they're supported. - // _GLIBCXX_FORMAT_F128=1 means __float128, _Float128 etc. will be formatted - // by converting them to long double (or __ieee128 for powerpc64le). - // _GLIBCXX_FORMAT_F128=2 means basic_format_arg needs to enable explicit - // support for _Float128, rather than formatting it as another type. + // The __float128, _Float128 will be formatted by converting them to: + // __ieee128 (same as __float128) when _GLIBCXX_FORMAT_F128=1, + // long double when _GLIBCXX_FORMAT_F128=2, + // _Float128 when _GLIBCXX_FORMAT_F128=3. #undef _GLIBCXX_FORMAT_F128 #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT // Format 128-bit floating-point types using __ieee128. - using __float128_t = __ieee128; + using __flt128_t = __ieee128; # define _GLIBCXX_FORMAT_F128 1 #ifdef __LONG_DOUBLE_IEEE128__ @@ -1910,14 +1922,14 @@ namespace __format #elif defined _GLIBCXX_LDOUBLE_IS_IEEE_BINARY128 // Format 128-bit floating-point types using long double. - using __float128_t = long double; -# define _GLIBCXX_FORMAT_F128 1 + using __flt128_t = long double; +# define _GLIBCXX_FORMAT_F128 2 #elif __FLT128_DIG__ && defined(_GLIBCXX_HAVE_FLOAT128_MATH) // Format 128-bit floating-point types using _Float128. - using __float128_t = _Float128; -# define _GLIBCXX_FORMAT_F128 2 + using __flt128_t = _Float128; +# define _GLIBCXX_FORMAT_F128 3 # if __cplusplus == 202002L // These overloads exist in the library, but are not declared for C++20. @@ -2386,9 +2398,16 @@ namespace __format const size_t __r = __str.size() - __e; // Length of remainder. auto __overwrite = [&](_CharT* __p, size_t) { // Apply grouping to the digits before the radix or exponent. - auto __end = std::__add_grouping(__p, __np.thousands_sep(), + int __off = 0; + if (auto __c = __str.front(); __c == '-' || __c == '+' || __c == ' ') + { + *__p = __c; + __off = 1; + } + auto __end = std::__add_grouping(__p + __off, __np.thousands_sep(), __grp.data(), __grp.size(), - __str.data(), __str.data() + __e); + __str.data() + __off, + __str.data() + __e); if (__r) // If there's a fractional part or exponent { if (__d != __str.npos) @@ -2419,17 +2438,18 @@ namespace __format constexpr __formatter_ptr(_Spec<_CharT> __spec) noexcept : _M_spec(__spec) - { } + { _M_set_default(_Pres_p); } constexpr typename basic_format_parse_context<_CharT>::iterator - parse(basic_format_parse_context<_CharT>& __pc) + parse(basic_format_parse_context<_CharT>& __pc, _Pres_type __type = _Pres_p) { __format::_Spec<_CharT> __spec{}; const auto __last = __pc.end(); auto __first = __pc.begin(); - auto __finalize = [this, &__spec] { + auto __finalize = [this, &__spec, __type] { _M_spec = __spec; + _M_set_default(__type); }; auto __finished = [&] { @@ -2457,19 +2477,23 @@ namespace __format #endif __first = __spec._M_parse_width(__first, __last, __pc); + if (__finished()) + return __first; - if (__first != __last) + if (*__first == 'p') { - if (*__first == 'p') - ++__first; + __spec._M_type = _Pres_p; + _M_spec._M_alt = !_M_spec._M_alt; + ++__first; + } #if __glibcxx_format >= 202304L - else if (*__first == 'P') - { - __spec._M_type = __format::_Pres_P; - ++__first; - } -#endif + else if (*__first == 'P') + { + __spec._M_type = _Pres_P; + _M_spec._M_alt = !_M_spec._M_alt; + ++__first; } +#endif if (__finished()) return __first; @@ -2536,6 +2560,17 @@ namespace __format } private: + [[__gnu__::__always_inline__]] + constexpr void + _M_set_default(_Pres_type __type) + { + if (_M_spec._M_type == _Pres_none && __type != _Pres_none) + { + _M_spec._M_type = __type; + _M_spec._M_alt = !_M_spec._M_alt; + } + } + __format::_Spec<_CharT> _M_spec{}; }; @@ -2558,11 +2593,8 @@ namespace __format typename basic_format_context<_Out, _CharT>::iterator format(_CharT __u, basic_format_context<_Out, _CharT>& __fc) const { - if (_M_f._M_spec._M_type == __format::_Pres_none - || _M_f._M_spec._M_type == __format::_Pres_c) + if (_M_f._M_spec._M_type == __format::_Pres_c) return _M_f._M_format_character(__u, __fc); - else if (_M_f._M_spec._M_type == __format::_Pres_esc) - return _M_f._M_format_character_escaped(__u, __fc); else return _M_f.format(static_cast<make_unsigned_t<_CharT>>(__u), __fc); } @@ -2570,7 +2602,7 @@ namespace __format #if __glibcxx_format_ranges // C++ >= 23 && HOSTED constexpr void set_debug_format() noexcept - { _M_f._M_spec._M_type = __format::_Pres_esc; } + { _M_f._M_spec._M_debug = true; } #endif private: @@ -2594,11 +2626,8 @@ namespace __format typename basic_format_context<_Out, wchar_t>::iterator format(char __u, basic_format_context<_Out, wchar_t>& __fc) const { - if (_M_f._M_spec._M_type == __format::_Pres_none - || _M_f._M_spec._M_type == __format::_Pres_c) + if (_M_f._M_spec._M_type == __format::_Pres_c) return _M_f._M_format_character(__u, __fc); - else if (_M_f._M_spec._M_type == __format::_Pres_esc) - return _M_f._M_format_character_escaped(__u, __fc); else return _M_f.format(static_cast<unsigned char>(__u), __fc); } @@ -2606,7 +2635,7 @@ namespace __format #if __glibcxx_format_ranges // C++ >= 23 && HOSTED constexpr void set_debug_format() noexcept - { _M_f._M_spec._M_type = __format::_Pres_esc; } + { _M_f._M_spec._M_debug = true; } #endif private: @@ -2947,8 +2976,8 @@ namespace __format }; #endif -#if defined(__FLT128_DIG__) && _GLIBCXX_FORMAT_F128 == 1 - // Reuse __formatter_fp<C>::format<__float128_t, Out> for _Float128. +#if defined(__FLT128_DIG__) && _GLIBCXX_FORMAT_F128 + // Use __formatter_fp<C>::format<__format::__flt128_t, Out> for _Float128. template<__format::__char _CharT> struct formatter<_Float128, _CharT> { @@ -2962,17 +2991,45 @@ namespace __format template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(_Float128 __u, basic_format_context<_Out, _CharT>& __fc) const - { return _M_f.format((__format::__float128_t)__u, __fc); } + { return _M_f.format((__format::__flt128_t)__u, __fc); } + + private: + __format::__formatter_fp<_CharT> _M_f; + }; +#endif + +#if defined(__SIZEOF_FLOAT128__) && _GLIBCXX_FORMAT_F128 > 1 + // Reuse __formatter_fp<C>::format<__format::__flt128_t, Out> for __float128. + // This formatter is not declared if _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT is true, + // as __float128 when present is same type as __ieee128, which may be same as + // long double. + template<__format::__char _CharT> + struct formatter<__float128, _CharT> + { + formatter() = default; + + [[__gnu__::__always_inline__]] + constexpr typename basic_format_parse_context<_CharT>::iterator + parse(basic_format_parse_context<_CharT>& __pc) + { return _M_f.parse(__pc); } + + template<typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + format(__float128 __u, basic_format_context<_Out, _CharT>& __fc) const + { return _M_f.format((__format::__flt128_t)__u, __fc); } private: __format::__formatter_fp<_CharT> _M_f; + + static_assert( !is_same_v<__float128, long double>, + "This specialization should not be used for long double" ); }; #endif #if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) // Reuse __formatter_fp<C>::format<float, Out> for bfloat16_t. template<__format::__char _CharT> - struct formatter<__gnu_cxx::__bfloat16_t, _CharT> + struct formatter<__format::__bflt16_t, _CharT> { formatter() = default; @@ -3057,24 +3114,28 @@ namespace __format // _GLIBCXX_RESOLVE_LIB_DEFECTS // 3944. Formatters converting sequences of char to sequences of wchar_t - namespace __format { struct __disabled; } + struct __formatter_disabled + { + __formatter_disabled() = delete; // Cannot format char sequence to wchar_t + __formatter_disabled(const __formatter_disabled&) = delete; + __formatter_disabled& operator=(const __formatter_disabled&) = delete; + }; - // std::formatter<__disabled, C> uses the primary template, which is disabled. template<> struct formatter<char*, wchar_t> - : private formatter<__format::__disabled, wchar_t> { }; + : private __formatter_disabled { }; template<> struct formatter<const char*, wchar_t> - : private formatter<__format::__disabled, wchar_t> { }; + : private __formatter_disabled { }; template<size_t _Nm> struct formatter<char[_Nm], wchar_t> - : private formatter<__format::__disabled, wchar_t> { }; + : private __formatter_disabled { }; template<class _Traits, class _Allocator> struct formatter<basic_string<char, _Traits, _Allocator>, wchar_t> - : private formatter<__format::__disabled, wchar_t> { }; + : private __formatter_disabled { }; template<class _Traits> struct formatter<basic_string_view<char, _Traits>, wchar_t> - : private formatter<__format::__disabled, wchar_t> { }; + : private __formatter_disabled { }; #endif /// An iterator after the last character written, and the number of @@ -3832,20 +3893,19 @@ namespace __format } }; - enum _Arg_t : unsigned char { + enum class _Arg_t : unsigned char { _Arg_none, _Arg_bool, _Arg_c, _Arg_i, _Arg_u, _Arg_ll, _Arg_ull, _Arg_flt, _Arg_dbl, _Arg_ldbl, _Arg_str, _Arg_sv, _Arg_ptr, _Arg_handle, - _Arg_i128, _Arg_u128, - _Arg_bf16, _Arg_f16, _Arg_f32, _Arg_f64, // These are unused. + _Arg_i128, _Arg_u128, _Arg_float128, + _Arg_bf16, _Arg_f16, _Arg_f32, _Arg_f64, + _Arg_max_, + #ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT - _Arg_next_value_, - _Arg_f128 = _Arg_ldbl, - _Arg_ibm128 = _Arg_next_value_, -#else - _Arg_f128, + _Arg_ibm128 = _Arg_ldbl, + _Arg_ieee128 = _Arg_float128, #endif - _Arg_max_ }; + using enum _Arg_t; template<typename _Context> struct _Arg_value @@ -3871,6 +3931,12 @@ namespace __format double _M_dbl; #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT // No long double if it's ambiguous. long double _M_ldbl; +#else + __ibm128 _M_ibm128; + __ieee128 _M_ieee128; +#endif +#ifdef __SIZEOF_FLOAT128__ + __float128 _M_float128; #endif const _CharT* _M_str; basic_string_view<_CharT> _M_sv; @@ -3880,11 +3946,17 @@ namespace __format __int128 _M_i128; unsigned __int128 _M_u128; #endif -#ifdef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT - __ieee128 _M_f128; - __ibm128 _M_ibm128; -#elif _GLIBCXX_FORMAT_F128 == 2 - __float128_t _M_f128; +#ifdef __BFLT16_DIG__ + __bflt16_t _M_bf16; +#endif +#ifdef __FLT16_DIG__ + _Float16 _M_f16; +#endif +#ifdef __FLT32_DIG__ + _Float32 _M_f32; +#endif +#ifdef __FLT64_DIG__ + _Float64 _M_f64; #endif }; @@ -3922,10 +3994,14 @@ namespace __format else if constexpr (is_same_v<_Tp, long double>) return __u._M_ldbl; #else - else if constexpr (is_same_v<_Tp, __ieee128>) - return __u._M_f128; else if constexpr (is_same_v<_Tp, __ibm128>) return __u._M_ibm128; + else if constexpr (is_same_v<_Tp, __ieee128>) + return __u._M_ieee128; +#endif +#ifdef __SIZEOF_FLOAT128__ + else if constexpr (is_same_v<_Tp, __float128>) + return __u._M_float128; #endif else if constexpr (is_same_v<_Tp, const _CharT*>) return __u._M_str; @@ -3939,9 +4015,21 @@ namespace __format else if constexpr (is_same_v<_Tp, unsigned __int128>) return __u._M_u128; #endif -#if _GLIBCXX_FORMAT_F128 == 2 - else if constexpr (is_same_v<_Tp, __float128_t>) - return __u._M_f128; +#ifdef __BFLT16_DIG__ + else if constexpr (is_same_v<_Tp, __bflt16_t>) + return __u._M_bf16; +#endif +#ifdef __FLT16_DIG__ + else if constexpr (is_same_v<_Tp, _Float16>) + return __u._M_f16; +#endif +#ifdef __FLT32_DIG__ + else if constexpr (is_same_v<_Tp, _Float32>) + return __u._M_f32; +#endif +#ifdef __FLT64_DIG__ + else if constexpr (is_same_v<_Tp, _Float64>) + return __u._M_f64; #endif else if constexpr (derived_from<_Tp, _HandleBase>) return static_cast<_Tp&>(__u._M_handle); @@ -4120,36 +4208,25 @@ namespace __format else if constexpr (is_same_v<_Td, __ieee128>) return type_identity<__ieee128>(); #endif - -#if defined(__FLT16_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) - else if constexpr (is_same_v<_Td, _Float16>) - return type_identity<float>(); +#if defined(__SIZEOF_FLOAT128__) && _GLIBCXX_FORMAT_F128 + else if constexpr (is_same_v<_Td, __float128>) + return type_identity<__float128>(); #endif - -#if defined(__BFLT16_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) - else if constexpr (is_same_v<_Td, decltype(0.0bf16)>) - return type_identity<float>(); +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + else if constexpr (is_same_v<_Td, __format::__bflt16_t>) + return type_identity<__format::__bflt16_t>(); +#endif +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + else if constexpr (is_same_v<_Td, _Float16>) + return type_identity<_Float16>(); #endif - #if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) else if constexpr (is_same_v<_Td, _Float32>) - return type_identity<float>(); + return type_identity<_Float32>(); #endif - #if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) else if constexpr (is_same_v<_Td, _Float64>) - return type_identity<double>(); -#endif - -#if _GLIBCXX_FORMAT_F128 -# if __FLT128_DIG__ - else if constexpr (is_same_v<_Td, _Float128>) - return type_identity<__format::__float128_t>(); -# endif -# if __SIZEOF_FLOAT128__ - else if constexpr (is_same_v<_Td, __float128>) - return type_identity<__format::__float128_t>(); -# endif + return type_identity<_Float64>(); #endif else if constexpr (__is_specialization_of<_Td, basic_string_view> || __is_specialization_of<_Td, basic_string>) @@ -4205,7 +4282,27 @@ namespace __format else if constexpr (is_same_v<_Tp, __ibm128>) return _Arg_ibm128; else if constexpr (is_same_v<_Tp, __ieee128>) - return _Arg_f128; + return _Arg_ieee128; +#endif +#if defined(__SIZEOF_FLOAT128__) && _GLIBCXX_FORMAT_F128 + else if constexpr (is_same_v<_Tp, __float128>) + return _Arg_float128; +#endif +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + else if constexpr (is_same_v<_Tp, __format::__bflt16_t>) + return _Arg_bf16; +#endif +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + else if constexpr (is_same_v<_Tp, _Float16>) + return _Arg_f16; +#endif +#if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + else if constexpr (is_same_v<_Tp, _Float32>) + return _Arg_f32; +#endif +#if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + else if constexpr (is_same_v<_Tp, _Float64>) + return _Arg_f64; #endif else if constexpr (is_same_v<_Tp, const _CharT*>) return _Arg_str; @@ -4219,11 +4316,6 @@ namespace __format else if constexpr (is_same_v<_Tp, unsigned __int128>) return _Arg_u128; #endif - -#if _GLIBCXX_FORMAT_F128 == 2 - else if constexpr (is_same_v<_Tp, __format::__float128_t>) - return _Arg_f128; -#endif else if constexpr (is_same_v<_Tp, handle>) return _Arg_handle; } @@ -4296,13 +4388,33 @@ namespace __format #ifndef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT case _Arg_ldbl: return std::forward<_Visitor>(__vis)(_M_val._M_ldbl); +#if defined(__SIZEOF_FLOAT128__) && _GLIBCXX_FORMAT_F128 + case _Arg_float128: + return std::forward<_Visitor>(__vis)(_M_val._M_float128); +#endif #else - case _Arg_f128: - return std::forward<_Visitor>(__vis)(_M_val._M_f128); case _Arg_ibm128: return std::forward<_Visitor>(__vis)(_M_val._M_ibm128); + case _Arg_ieee128: + return std::forward<_Visitor>(__vis)(_M_val._M_ieee128); +#endif +#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + case _Arg_bf16: + return std::forward<_Visitor>(__vis)(_M_val._M_bf16); +#endif +#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + case _Arg_f16: + return std::forward<_Visitor>(__vis)(_M_val._M_f16); #endif +#if defined(__FLT32_DIG__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + case _Arg_f32: + return std::forward<_Visitor>(__vis)(_M_val._M_f32); +#endif +#if defined(__FLT64_DIG__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + case _Arg_f64: + return std::forward<_Visitor>(__vis)(_M_val._M_f64); #endif +#endif // __glibcxx_to_chars case _Arg_str: return std::forward<_Visitor>(__vis)(_M_val._M_str); case _Arg_sv: @@ -4320,14 +4432,7 @@ namespace __format case _Arg_u128: return std::forward<_Visitor>(__vis)(_M_val._M_u128); #endif - -#if _GLIBCXX_FORMAT_F128 == 2 - case _Arg_f128: - return std::forward<_Visitor>(__vis)(_M_val._M_f128); -#endif - default: - // _Arg_f16 etc. __builtin_unreachable(); } } @@ -4413,7 +4518,7 @@ namespace __format { __UINT64_TYPE__ __packed_types = 0; for (auto __i = __types.rbegin(); __i != __types.rend(); ++__i) - __packed_types = (__packed_types << _Bits) | *__i; + __packed_types = (__packed_types << _Bits) | (unsigned)*__i; return __packed_types; } } // namespace __format @@ -4426,7 +4531,7 @@ namespace __format static constexpr int _S_packed_type_mask = 0b11111; static constexpr int _S_max_packed_args = 12; - static_assert( __format::_Arg_max_ <= (1 << _S_packed_type_bits) ); + static_assert( (unsigned)__format::_Arg_max_ <= (1u << _S_packed_type_bits) ); template<typename... _Args> using _Store = __format::_Arg_store<_Context, _Args...>; @@ -5378,24 +5483,7 @@ namespace __format #endif #if __glibcxx_format_ranges // C++ >= 23 && HOSTED - // [format.range], formatting of ranges - // [format.range.fmtkind], variable template format_kind - enum class range_format { - disabled, - map, - set, - sequence, - string, - debug_string - }; - /// @cond undocumented - template<typename _Rg> - constexpr auto format_kind = - __primary_template_not_defined( - format_kind<_Rg> // you can specialize this for non-const input ranges - ); - template<typename _Tp> consteval range_format __fmt_kind() @@ -5765,7 +5853,7 @@ namespace __format if (*__first == '?') { ++__first; - __spec._M_type = __format::_Pres_esc; + __spec._M_debug = true; if (__finished() || *__first != 's') __throw_format_error("format error: '?' is allowed only in" " combination with 's'"); @@ -5776,8 +5864,7 @@ namespace __format ++__first; if constexpr (same_as<_Tp, _CharT>) { - if (__spec._M_type != __format::_Pres_esc) - __spec._M_type = __format::_Pres_str; + __spec._M_type = __format::_Pres_s; if (__finished()) return __finalize(); __throw_format_error("format error: element format specifier" @@ -5859,8 +5946,7 @@ namespace __format _M_format(_Rg& __rg, basic_format_context<_Out, _CharT>& __fc) const { if constexpr (same_as<_Tp, _CharT>) - if (_M_spec._M_type == __format::_Pres_str - || _M_spec._M_type == __format::_Pres_esc) + if (_M_spec._M_type == __format::_Pres_s) { __format::__formatter_str __fstr(_M_spec); return __fstr._M_format_range(__rg, __fc); diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 1077e96..307bcb9 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -52,6 +52,21 @@ #if __cplusplus >= 201103L +#define __glibcxx_want_boyer_moore_searcher +#define __glibcxx_want_bind_front +#define __glibcxx_want_bind_back +#define __glibcxx_want_constexpr_functional +#define __glibcxx_want_copyable_function +#define __glibcxx_want_function_ref +#define __glibcxx_want_invoke +#define __glibcxx_want_invoke_r +#define __glibcxx_want_move_only_function +#define __glibcxx_want_not_fn +#define __glibcxx_want_ranges +#define __glibcxx_want_reference_wrapper +#define __glibcxx_want_transparent_operators +#include <bits/version.h> + #include <tuple> #include <type_traits> #include <bits/functional_hash.h> @@ -72,23 +87,10 @@ # include <bits/ranges_cmp.h> // std::identity, ranges::equal_to etc. # include <compare> #endif -#if __cplusplus > 202002L && _GLIBCXX_HOSTED -# include <bits/move_only_function.h> +#if __glibcxx_move_only_function || __glibcxx_copyable_function || __glibcxx_function_ref +# include <bits/funcwrap.h> #endif -#define __glibcxx_want_boyer_moore_searcher -#define __glibcxx_want_bind_front -#define __glibcxx_want_bind_back -#define __glibcxx_want_constexpr_functional -#define __glibcxx_want_invoke -#define __glibcxx_want_invoke_r -#define __glibcxx_want_move_only_function -#define __glibcxx_want_not_fn -#define __glibcxx_want_ranges -#define __glibcxx_want_reference_wrapper -#define __glibcxx_want_transparent_operators -#include <bits/version.h> - #endif // C++11 namespace std _GLIBCXX_VISIBILITY(default) diff --git a/libstdc++-v3/include/std/latch b/libstdc++-v3/include/std/latch index dc147c2..9504df0 100644 --- a/libstdc++-v3/include/std/latch +++ b/libstdc++-v3/include/std/latch @@ -89,15 +89,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_ALWAYS_INLINE void wait() const noexcept { - auto const __pred = [this] { return this->try_wait(); }; - std::__atomic_wait_address(&_M_counter, __pred); + auto const __vfn = [this] { + return __atomic_impl::load(&_M_counter, memory_order::acquire); + }; + auto const __pred = [](__detail::__platform_wait_t __v) { + return __v == 0; + }; + std::__atomic_wait_address(&_M_counter, __pred, __vfn); } _GLIBCXX_ALWAYS_INLINE void arrive_and_wait(ptrdiff_t __update = 1) noexcept { - count_down(__update); - wait(); + // The standard specifies this functions as count_down(update); wait(); + // but we combine those two calls into one and avoid the wait() if we + // know the counter reached zero. + + __glibcxx_assert(__update >= 0 && __update <= max()); + // Use acq_rel here because an omitted wait() would have used acquire: + auto const __old = __atomic_impl::fetch_sub(&_M_counter, __update, + memory_order::acq_rel); + if (std::cmp_equal(__old, __update)) + __atomic_impl::notify_all(&_M_counter); + else + { + __glibcxx_assert(std::cmp_less(__update, __old)); + wait(); + } } private: diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan index aee96dd..c72a640 100644 --- a/libstdc++-v3/include/std/mdspan +++ b/libstdc++-v3/include/std/mdspan @@ -69,12 +69,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // // If __r is the index of a dynamic extent, then // _S_dynamic_index[__r] is the index of that extent in - // _M_dynamic_extents. + // _M_dyn_exts. static constexpr auto _S_dynamic_index = [] consteval { array<size_t, _S_rank+1> __ret; size_t __dyn = 0; - for(size_t __i = 0; __i < _S_rank; ++__i) + for (size_t __i = 0; __i < _S_rank; ++__i) { __ret[__i] = __dyn; __dyn += _S_is_dyn(_Extents[__i]); @@ -105,7 +105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { auto __se = _Extents[__r]; if (__se == dynamic_extent) - return _M_dynamic_extents[_S_dynamic_index[__r]]; + return _M_dyn_exts[_S_dynamic_index[__r]]; else return __se; } @@ -114,12 +114,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr void _M_init_dynamic_extents(_GetOtherExtent __get_extent) noexcept { - for(size_t __i = 0; __i < _S_rank_dynamic; ++__i) + for (size_t __i = 0; __i < _S_rank_dynamic; ++__i) { size_t __di = __i; if constexpr (_OtherRank != _S_rank_dynamic) __di = _S_dynamic_index_inv[__i]; - _M_dynamic_extents[__i] = _S_int_cast(__get_extent(__di)); + _M_dyn_exts[__i] = _S_int_cast(__get_extent(__di)); } } @@ -144,9 +144,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __exts[__i]; }); } + static constexpr span<const size_t> + _S_static_extents(size_t __begin, size_t __end) noexcept + { + return {_Extents.data() + __begin, _Extents.data() + __end}; + } + + constexpr span<const _IndexType> + _M_dynamic_extents(size_t __begin, size_t __end) const noexcept + requires (_Extents.size() > 0) + { + return {_M_dyn_exts + _S_dynamic_index[__begin], + _M_dyn_exts + _S_dynamic_index[__end]}; + } + private: using _S_storage = __array_traits<_IndexType, _S_rank_dynamic>::_Type; - [[no_unique_address]] _S_storage _M_dynamic_extents; + [[no_unique_address]] _S_storage _M_dyn_exts{}; }; template<typename _OIndexType, typename _SIndexType> @@ -160,13 +174,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION || _Extent <= numeric_limits<_IndexType>::max(); } + namespace __mdspan + { + template<typename _Extents> + constexpr span<const size_t> + __static_extents(size_t __begin = 0, size_t __end = _Extents::rank()) + noexcept + { return _Extents::_S_storage::_S_static_extents(__begin, __end); } + + template<typename _Extents> + constexpr span<const typename _Extents::index_type> + __dynamic_extents(const _Extents& __exts, size_t __begin = 0, + size_t __end = _Extents::rank()) noexcept + { + return __exts._M_exts._M_dynamic_extents(__begin, __end); + } + } + template<typename _IndexType, size_t... _Extents> class extents { - static_assert(is_integral_v<_IndexType>, "_IndexType must be integral."); + static_assert(__is_standard_integer<_IndexType>::value, + "IndexType must be a signed or unsigned integer type"); static_assert( (__mdspan::__valid_static_extent<_Extents, _IndexType> && ...), - "Extents must either be dynamic or representable as _IndexType"); + "Extents must either be dynamic or representable as IndexType"); public: using index_type = _IndexType; @@ -196,7 +228,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if constexpr (rank() == 0) __builtin_trap(); else - return _M_dynamic_extents._M_extent(__r); + return _M_exts._M_extent(__r); } constexpr @@ -232,14 +264,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION requires (_S_is_compatible_extents<_OExtents...>()) constexpr explicit(_S_ctor_explicit<_OIndexType, _OExtents...>()) extents(const extents<_OIndexType, _OExtents...>& __other) noexcept - : _M_dynamic_extents(__other._M_dynamic_extents) + : _M_exts(__other._M_exts) { } template<__mdspan::__valid_index_type<index_type>... _OIndexTypes> requires (sizeof...(_OIndexTypes) == rank() || sizeof...(_OIndexTypes) == rank_dynamic()) constexpr explicit extents(_OIndexTypes... __exts) noexcept - : _M_dynamic_extents(span<const _IndexType, sizeof...(_OIndexTypes)>( + : _M_exts(span<const _IndexType, sizeof...(_OIndexTypes)>( initializer_list{_S_storage::_S_int_cast(__exts)...})) { } @@ -247,15 +279,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION requires (_Nm == rank() || _Nm == rank_dynamic()) constexpr explicit(_Nm != rank_dynamic()) extents(span<_OIndexType, _Nm> __exts) noexcept - : _M_dynamic_extents(span<const _OIndexType, _Nm>(__exts)) + : _M_exts(span<const _OIndexType, _Nm>(__exts)) { } - template<__mdspan::__valid_index_type<index_type> _OIndexType, size_t _Nm> requires (_Nm == rank() || _Nm == rank_dynamic()) constexpr explicit(_Nm != rank_dynamic()) extents(const array<_OIndexType, _Nm>& __exts) noexcept - : _M_dynamic_extents(span<const _OIndexType, _Nm>(__exts)) + : _M_exts(span<const _OIndexType, _Nm>(__exts)) { } template<typename _OIndexType, size_t... _OExtents> @@ -275,9 +306,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } private: + friend span<const size_t> + __mdspan::__static_extents<extents>(size_t, size_t); + + friend span<const index_type> + __mdspan::__dynamic_extents<extents>(const extents&, size_t, size_t); + using _S_storage = __mdspan::_ExtentsStorage< _IndexType, array<size_t, sizeof...(_Extents)>{_Extents...}>; - [[no_unique_address]] _S_storage _M_dynamic_extents; + [[no_unique_address]] _S_storage _M_exts; template<typename _OIndexType, size_t... _OExtents> friend class extents; @@ -285,6 +322,69 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION namespace __mdspan { + template<typename _Tp, size_t _Nm> + constexpr bool + __contains_zero(span<_Tp, _Nm> __exts) noexcept + { + for (size_t __i = 0; __i < __exts.size(); ++__i) + if (__exts[__i] == 0) + return true; + return false; + } + + template<typename _Extents> + constexpr bool + __empty(const _Extents& __exts) noexcept + { + if constexpr (__contains_zero(__static_extents<_Extents>())) + return true; + else if constexpr (_Extents::rank_dynamic() > 0) + return __contains_zero(__dynamic_extents(__exts)); + else + return false; + } + + constexpr size_t + __static_extents_prod(const auto& __sta_exts) noexcept + { + size_t __ret = 1; + for (auto __factor : __sta_exts) + if (__factor != dynamic_extent) + __ret *= __factor; + return __ret; + } + + template<typename _Extents> + constexpr typename _Extents::index_type + __exts_prod(const _Extents& __exts, size_t __begin, size_t __end) noexcept + { + using _IndexType = typename _Extents::index_type; + + size_t __ret = 1; + if constexpr (_Extents::rank_dynamic() != _Extents::rank()) + { + auto __sta_exts = __static_extents<_Extents>(__begin, __end); + __ret = __static_extents_prod(__sta_exts); + if (__ret == 0) + return 0; + } + + if constexpr (_Extents::rank_dynamic() > 0) + for (auto __factor : __dynamic_extents(__exts, __begin, __end)) + __ret *= size_t(__factor); + return _IndexType(__ret); + } + + template<typename _Extents> + constexpr typename _Extents::index_type + __fwd_prod(const _Extents& __exts, size_t __r) noexcept + { return __exts_prod(__exts, 0, __r); } + + template<typename _Extents> + constexpr typename _Extents::index_type + __rev_prod(const _Extents& __exts, size_t __r) noexcept + { return __exts_prod(__exts, __r + 1, __exts.rank()); } + template<typename _IndexType, size_t... _Counts> auto __build_dextents_type(integer_sequence<size_t, _Counts...>) -> extents<_IndexType, ((void) _Counts, dynamic_extent)...>; @@ -303,6 +403,638 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION explicit extents(_Integrals...) -> extents<size_t, __mdspan::__dynamic_extent<_Integrals>()...>; + struct layout_left + { + template<typename _Extents> + class mapping; + }; + + struct layout_right + { + template<typename _Extents> + class mapping; + }; + + struct layout_stride + { + template<typename _Extents> + class mapping; + }; + + namespace __mdspan + { + template<typename _Tp> + constexpr bool __is_extents = false; + + template<typename _IndexType, size_t... _Extents> + constexpr bool __is_extents<extents<_IndexType, _Extents...>> = true; + + template<typename _Extents, typename... _Indices> + constexpr typename _Extents::index_type + __linear_index_left(const _Extents& __exts, _Indices... __indices) + noexcept + { + using _IndexType = typename _Extents::index_type; + _IndexType __res = 0; + if constexpr (sizeof...(__indices) > 0) + { + _IndexType __mult = 1; + auto __update = [&, __pos = 0u](_IndexType __idx) mutable + { + __res += __idx * __mult; + __mult *= __exts.extent(__pos); + ++__pos; + }; + (__update(__indices), ...); + } + return __res; + } + + template<typename _Extents, + typename _IndexType = typename _Extents::index_type> + consteval _IndexType + __static_quotient(_IndexType __nom = numeric_limits<_IndexType>::max()) + { + auto __sta_exts = __static_extents<_Extents>(); + for (auto __factor : __sta_exts) + { + if (__factor != dynamic_extent) + __nom /= _IndexType(__factor); + if (__nom == 0) + break; + } + return __nom; + } + + template<typename _Extents> + constexpr bool + __is_representable_extents(const _Extents& __exts) noexcept + { + using _IndexType = _Extents::index_type; + + if constexpr (__contains_zero(__static_extents<_Extents>())) + return true; + else + { + constexpr auto __sta_quo = __static_quotient<_Extents>(); + if constexpr (_Extents::rank_dynamic() == 0) + return __sta_quo != 0; + else + { + auto __dyn_exts = __dynamic_extents(__exts); + if (__contains_zero(__dyn_exts)) + return true; + + if constexpr (__sta_quo == 0) + return false; + else + { + auto __dyn_quo = _IndexType(__sta_quo); + for (auto __factor : __dyn_exts) + { + __dyn_quo /= __factor; + if (__dyn_quo == 0) + return false; + } + return true; + } + } + } + } + + template<typename _Extents, typename _IndexType> + concept __representable_size = _Extents::rank_dynamic() != 0 + || __contains_zero(__static_extents<_Extents>()) + || (__static_quotient<_Extents, _IndexType>() != 0); + + template<typename _Layout, typename _Mapping> + concept __mapping_of = + is_same_v<typename _Layout::mapping<typename _Mapping::extents_type>, + _Mapping>; + + template<typename _Mapping> + concept __standardized_mapping = __mapping_of<layout_left, _Mapping> + || __mapping_of<layout_right, _Mapping> + || __mapping_of<layout_stride, _Mapping>; + + // A tag type to create internal ctors. + class __internal_ctor + { }; + } + + template<typename _Extents> + class layout_left::mapping + { + public: + using extents_type = _Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_left; + + static_assert(__mdspan::__representable_size<extents_type, index_type>, + "The size of extents_type must be representable as index_type"); + + constexpr + mapping() noexcept = default; + + constexpr + mapping(const mapping&) noexcept = default; + + constexpr + mapping(const extents_type& __extents) noexcept + : _M_extents(__extents) + { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); } + + template<typename _OExtents> + requires is_constructible_v<extents_type, _OExtents> + constexpr explicit(!is_convertible_v<_OExtents, extents_type>) + mapping(const mapping<_OExtents>& __other) noexcept + : mapping(__other.extents(), __mdspan::__internal_ctor{}) + { } + + template<typename _OExtents> + requires (extents_type::rank() <= 1) + && is_constructible_v<extents_type, _OExtents> + constexpr explicit(!is_convertible_v<_OExtents, extents_type>) + mapping(const layout_right::mapping<_OExtents>& __other) noexcept + : mapping(__other.extents(), __mdspan::__internal_ctor{}) + { } + + // noexcept for consistency with other layouts. + template<typename _OExtents> + requires is_constructible_v<extents_type, _OExtents> + constexpr explicit(extents_type::rank() > 0) + mapping(const layout_stride::mapping<_OExtents>& __other) noexcept + : mapping(__other.extents(), __mdspan::__internal_ctor{}) + { __glibcxx_assert(*this == __other); } + + constexpr mapping& + operator=(const mapping&) noexcept = default; + + constexpr const extents_type& + extents() const noexcept { return _M_extents; } + + constexpr index_type + required_span_size() const noexcept + { return __mdspan::__fwd_prod(_M_extents, extents_type::rank()); } + + template<__mdspan::__valid_index_type<index_type>... _Indices> + requires (sizeof...(_Indices) == extents_type::rank()) + constexpr index_type + operator()(_Indices... __indices) const noexcept + { + return __mdspan::__linear_index_left(_M_extents, + static_cast<index_type>(__indices)...); + } + + static constexpr bool + is_always_unique() noexcept { return true; } + + static constexpr bool + is_always_exhaustive() noexcept { return true; } + + static constexpr bool + is_always_strided() noexcept { return true; } + + static constexpr bool + is_unique() noexcept { return true; } + + static constexpr bool + is_exhaustive() noexcept { return true; } + + static constexpr bool + is_strided() noexcept { return true; } + + constexpr index_type + stride(rank_type __i) const noexcept + requires (extents_type::rank() > 0) + { + __glibcxx_assert(__i < extents_type::rank()); + return __mdspan::__fwd_prod(_M_extents, __i); + } + + template<typename _OExtents> + requires (extents_type::rank() == _OExtents::rank()) + friend constexpr bool + operator==(const mapping& __self, const mapping<_OExtents>& __other) + noexcept + { return __self.extents() == __other.extents(); } + + private: + template<typename _OExtents> + constexpr explicit + mapping(const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept + : _M_extents(__oexts) + { + static_assert(__mdspan::__representable_size<_OExtents, index_type>, + "The size of OtherExtents must be representable as index_type"); + __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); + } + + [[no_unique_address]] extents_type _M_extents{}; + }; + + namespace __mdspan + { + template<typename _Extents, typename... _Indices> + constexpr typename _Extents::index_type + __linear_index_right(const _Extents& __exts, _Indices... __indices) + noexcept + { + using _IndexType = typename _Extents::index_type; + array<_IndexType, sizeof...(__indices)> __ind_arr{__indices...}; + _IndexType __res = 0; + if constexpr (sizeof...(__indices) > 0) + { + _IndexType __mult = 1; + auto __update = [&, __pos = __exts.rank()](_IndexType) mutable + { + --__pos; + __res += __ind_arr[__pos] * __mult; + __mult *= __exts.extent(__pos); + }; + (__update(__indices), ...); + } + return __res; + } + } + + template<typename _Extents> + class layout_right::mapping + { + public: + using extents_type = _Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_right; + + static_assert(__mdspan::__representable_size<extents_type, index_type>, + "The size of extents_type must be representable as index_type"); + + constexpr + mapping() noexcept = default; + + constexpr + mapping(const mapping&) noexcept = default; + + constexpr + mapping(const extents_type& __extents) noexcept + : _M_extents(__extents) + { __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); } + + template<typename _OExtents> + requires is_constructible_v<extents_type, _OExtents> + constexpr explicit(!is_convertible_v<_OExtents, extents_type>) + mapping(const mapping<_OExtents>& __other) noexcept + : mapping(__other.extents(), __mdspan::__internal_ctor{}) + { } + + template<typename _OExtents> + requires (extents_type::rank() <= 1) + && is_constructible_v<extents_type, _OExtents> + constexpr explicit(!is_convertible_v<_OExtents, extents_type>) + mapping(const layout_left::mapping<_OExtents>& __other) noexcept + : mapping(__other.extents(), __mdspan::__internal_ctor{}) + { } + + template<typename _OExtents> + requires is_constructible_v<extents_type, _OExtents> + constexpr explicit(extents_type::rank() > 0) + mapping(const layout_stride::mapping<_OExtents>& __other) noexcept + : mapping(__other.extents(), __mdspan::__internal_ctor{}) + { __glibcxx_assert(*this == __other); } + + constexpr mapping& + operator=(const mapping&) noexcept = default; + + constexpr const extents_type& + extents() const noexcept { return _M_extents; } + + constexpr index_type + required_span_size() const noexcept + { return __mdspan::__fwd_prod(_M_extents, extents_type::rank()); } + + template<__mdspan::__valid_index_type<index_type>... _Indices> + requires (sizeof...(_Indices) == extents_type::rank()) + constexpr index_type + operator()(_Indices... __indices) const noexcept + { + return __mdspan::__linear_index_right( + _M_extents, static_cast<index_type>(__indices)...); + } + + static constexpr bool + is_always_unique() noexcept + { return true; } + + static constexpr bool + is_always_exhaustive() noexcept + { return true; } + + static constexpr bool + is_always_strided() noexcept + { return true; } + + static constexpr bool + is_unique() noexcept + { return true; } + + static constexpr bool + is_exhaustive() noexcept + { return true; } + + static constexpr bool + is_strided() noexcept + { return true; } + + constexpr index_type + stride(rank_type __i) const noexcept + requires (extents_type::rank() > 0) + { + __glibcxx_assert(__i < extents_type::rank()); + return __mdspan::__rev_prod(_M_extents, __i); + } + + template<typename _OExtents> + requires (extents_type::rank() == _OExtents::rank()) + friend constexpr bool + operator==(const mapping& __self, const mapping<_OExtents>& __other) + noexcept + { return __self.extents() == __other.extents(); } + + private: + template<typename _OExtents> + constexpr explicit + mapping(const _OExtents& __oexts, __mdspan::__internal_ctor) noexcept + : _M_extents(__oexts) + { + static_assert(__mdspan::__representable_size<_OExtents, index_type>, + "The size of OtherExtents must be representable as index_type"); + __glibcxx_assert(__mdspan::__is_representable_extents(_M_extents)); + } + + [[no_unique_address]] extents_type _M_extents{}; + }; + + namespace __mdspan + { + template<typename _Mp> + concept __mapping_alike = requires + { + requires __is_extents<typename _Mp::extents_type>; + { _Mp::is_always_strided() } -> same_as<bool>; + { _Mp::is_always_exhaustive() } -> same_as<bool>; + { _Mp::is_always_unique() } -> same_as<bool>; + bool_constant<_Mp::is_always_strided()>::value; + bool_constant<_Mp::is_always_exhaustive()>::value; + bool_constant<_Mp::is_always_unique()>::value; + }; + + template<typename _Mapping> + constexpr typename _Mapping::index_type + __offset(const _Mapping& __m) noexcept + { + using _IndexType = typename _Mapping::index_type; + constexpr auto __rank = _Mapping::extents_type::rank(); + + if constexpr (__standardized_mapping<_Mapping>) + return 0; + else if (__empty(__m.extents())) + return 0; + else + { + auto __impl = [&__m]<size_t... _Counts>(index_sequence<_Counts...>) + { return __m(((void) _Counts, _IndexType(0))...); }; + return __impl(make_index_sequence<__rank>()); + } + } + + template<typename _Mapping, typename... _Indices> + constexpr typename _Mapping::index_type + __linear_index_strides(const _Mapping& __m, _Indices... __indices) + noexcept + { + using _IndexType = typename _Mapping::index_type; + _IndexType __res = 0; + if constexpr (sizeof...(__indices) > 0) + { + auto __update = [&, __pos = 0u](_IndexType __idx) mutable + { + __res += __idx * __m.stride(__pos++); + }; + (__update(__indices), ...); + } + return __res; + } + } + + template<typename _Extents> + class layout_stride::mapping + { + public: + using extents_type = _Extents; + using index_type = typename extents_type::index_type; + using size_type = typename extents_type::size_type; + using rank_type = typename extents_type::rank_type; + using layout_type = layout_stride; + + static_assert(__mdspan::__representable_size<extents_type, index_type>, + "The size of extents_type must be representable as index_type"); + + constexpr + mapping() noexcept + { + // The precondition is either statically asserted, or automatically + // satisfied because dynamic extents are zero-initialized. + size_t __stride = 1; + for (size_t __i = extents_type::rank(); __i > 0; --__i) + { + _M_strides[__i - 1] = index_type(__stride); + __stride *= size_t(_M_extents.extent(__i - 1)); + } + } + + constexpr + mapping(const mapping&) noexcept = default; + + template<__mdspan::__valid_index_type<index_type> _OIndexType> + constexpr + mapping(const extents_type& __exts, + span<_OIndexType, extents_type::rank()> __strides) noexcept + : _M_extents(__exts) + { + for (size_t __i = 0; __i < extents_type::rank(); ++__i) + _M_strides[__i] = index_type(as_const(__strides[__i])); + } + + template<__mdspan::__valid_index_type<index_type> _OIndexType> + constexpr + mapping(const extents_type& __exts, + const array<_OIndexType, extents_type::rank()>& __strides) + noexcept + : mapping(__exts, + span<const _OIndexType, extents_type::rank()>(__strides)) + { } + + template<__mdspan::__mapping_alike _StridedMapping> + requires (is_constructible_v<extents_type, + typename _StridedMapping::extents_type> + && _StridedMapping::is_always_unique() + && _StridedMapping::is_always_strided()) + constexpr explicit(!( + is_convertible_v<typename _StridedMapping::extents_type, extents_type> + && __mdspan::__standardized_mapping<_StridedMapping>)) + mapping(const _StridedMapping& __other) noexcept + : _M_extents(__other.extents()) + { + using _OIndexType = _StridedMapping::index_type; + using _OExtents = _StridedMapping::extents_type; + + __glibcxx_assert(__mdspan::__offset(__other) == 0); + static_assert(__mdspan::__representable_size<_OExtents, index_type>, + "The size of StridedMapping::extents_type must be representable as" + " index_type"); + if constexpr (cmp_greater(numeric_limits<_OIndexType>::max(), + numeric_limits<index_type>::max())) + __glibcxx_assert(!cmp_less(numeric_limits<index_type>::max(), + __other.required_span_size()) + && "other.required_span_size() must be representable" + " as index_type"); + if constexpr (extents_type::rank() > 0) + for (size_t __i = 0; __i < extents_type::rank(); ++__i) + _M_strides[__i] = index_type(__other.stride(__i)); + } + + constexpr mapping& + operator=(const mapping&) noexcept = default; + + constexpr const extents_type& + extents() const noexcept { return _M_extents; } + + constexpr array<index_type, extents_type::rank()> + strides() const noexcept + { + array<index_type, extents_type::rank()> __ret; + for (size_t __i = 0; __i < extents_type::rank(); ++__i) + __ret[__i] = _M_strides[__i]; + return __ret; + } + + constexpr index_type + required_span_size() const noexcept + { + if (__mdspan::__empty(_M_extents)) + return 0; + + index_type __ret = 1; + for (size_t __i = 0; __i < extents_type::rank(); ++__i) + __ret += (_M_extents.extent(__i) - 1) * _M_strides[__i]; + return __ret; + } + + template<__mdspan::__valid_index_type<index_type>... _Indices> + requires (sizeof...(_Indices) == extents_type::rank()) + constexpr index_type + operator()(_Indices... __indices) const noexcept + { + return __mdspan::__linear_index_strides(*this, + static_cast<index_type>(__indices)...); + } + + static constexpr bool + is_always_unique() noexcept { return true; } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4266. layout_stride::mapping should treat empty mappings as exhaustive + static constexpr bool + is_always_exhaustive() noexcept + { + return (_Extents::rank() == 0) || __mdspan::__contains_zero( + __mdspan::__static_extents<extents_type>()); + } + + static constexpr bool + is_always_strided() noexcept { return true; } + + static constexpr bool + is_unique() noexcept { return true; } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4266. layout_stride::mapping should treat empty mappings as exhaustive + constexpr bool + is_exhaustive() const noexcept + { + if constexpr (!is_always_exhaustive()) + { + constexpr auto __rank = extents_type::rank(); + auto __size = __mdspan::__fwd_prod(_M_extents, __rank); + if(__size > 0) + return __size == required_span_size(); + } + return true; + } + + static constexpr bool + is_strided() noexcept { return true; } + + constexpr index_type + stride(rank_type __r) const noexcept { return _M_strides[__r]; } + + template<__mdspan::__mapping_alike _OMapping> + requires ((extents_type::rank() == _OMapping::extents_type::rank()) + && _OMapping::is_always_strided()) + friend constexpr bool + operator==(const mapping& __self, const _OMapping& __other) noexcept + { + if (__self.extents() != __other.extents()) + return false; + if constexpr (extents_type::rank() > 0) + for (size_t __i = 0; __i < extents_type::rank(); ++__i) + if (!cmp_equal(__self.stride(__i), __other.stride(__i))) + return false; + return __mdspan::__offset(__other) == 0; + } + + private: + using _S_strides_t = typename __array_traits<index_type, + extents_type::rank()>::_Type; + [[no_unique_address]] extents_type _M_extents; + [[no_unique_address]] _S_strides_t _M_strides; + }; + + template<typename _ElementType> + struct default_accessor + { + static_assert(!is_array_v<_ElementType>, + "ElementType must not be an array type"); + static_assert(!is_abstract_v<_ElementType>, + "ElementType must not be an abstract class type"); + + using offset_policy = default_accessor; + using element_type = _ElementType; + using reference = element_type&; + using data_handle_type = element_type*; + + constexpr + default_accessor() noexcept = default; + + template<typename _OElementType> + requires is_convertible_v<_OElementType(*)[], element_type(*)[]> + constexpr + default_accessor(default_accessor<_OElementType>) noexcept + { } + + constexpr reference + access(data_handle_type __p, size_t __i) const noexcept + { return __p[__i]; } + + constexpr data_handle_type + offset(data_handle_type __p, size_t __i) const noexcept + { return __p + __i; } + }; + _GLIBCXX_END_NAMESPACE_VERSION } #endif diff --git a/libstdc++-v3/include/std/memory b/libstdc++-v3/include/std/memory index 78a1250..1da03b3 100644 --- a/libstdc++-v3/include/std/memory +++ b/libstdc++-v3/include/std/memory @@ -97,6 +97,10 @@ # include <bits/out_ptr.h> #endif +#if __cplusplus > 202302L +# include <bits/indirect.h> +#endif + #define __glibcxx_want_addressof_constexpr #define __glibcxx_want_allocator_traits_is_always_equal #define __glibcxx_want_assume_aligned @@ -105,9 +109,11 @@ #define __glibcxx_want_constexpr_dynamic_alloc #define __glibcxx_want_constexpr_memory #define __glibcxx_want_enable_shared_from_this +#define __glibcxx_want_indirect #define __glibcxx_want_make_unique #define __glibcxx_want_out_ptr #define __glibcxx_want_parallel_algorithm +#define __glibcxx_want_polymorphic #define __glibcxx_want_ranges #define __glibcxx_want_raw_memory_algorithms #define __glibcxx_want_shared_ptr_arrays diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional index a616dc0..cc7af5b 100644 --- a/libstdc++-v3/include/std/optional +++ b/libstdc++-v3/include/std/optional @@ -36,6 +36,7 @@ #define __glibcxx_want_freestanding_optional #define __glibcxx_want_optional +#define __glibcxx_want_optional_range_support #define __glibcxx_want_constrained_equality #include <bits/version.h> @@ -57,6 +58,11 @@ #if __cplusplus > 202002L # include <concepts> #endif +#ifdef __cpp_lib_optional_range_support // C++ >= 26 +# include <bits/formatfwd.h> +# include <bits/ranges_base.h> +# include <bits/stl_iterator.h> +#endif namespace std _GLIBCXX_VISIBILITY(default) { @@ -858,6 +864,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public: using value_type = _Tp; +#ifdef __cpp_lib_optional_range_support // >= C++26 + using iterator = __gnu_cxx::__normal_iterator<_Tp*, optional>; + using const_iterator = __gnu_cxx::__normal_iterator<const _Tp*, optional>; +#endif constexpr optional() noexcept { } @@ -1158,6 +1168,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } +#ifdef __cpp_lib_optional_range_support // >= C++26 + // Iterator support. + constexpr iterator begin() noexcept + { + return iterator( + this->_M_is_engaged() ? std::addressof(this->_M_get()) : nullptr + ); + } + + constexpr const_iterator begin() const noexcept + { + return const_iterator( + this->_M_is_engaged() ? std::addressof(this->_M_get()) : nullptr + ); + } + + constexpr iterator end() noexcept + { + return begin() + has_value(); + } + + constexpr const_iterator end() const noexcept + { + return begin() + has_value(); + } +#endif // __cpp_lib_optional_range_support + // Observers. constexpr const _Tp* operator->() const noexcept @@ -1772,6 +1809,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template <typename _Tp> optional(_Tp) -> optional<_Tp>; #endif +#ifdef __cpp_lib_optional_range_support // >= C++26 + template<typename _Tp> + inline constexpr bool + ranges::enable_view<optional<_Tp>> = true; + + template<typename _Tp> + inline constexpr range_format + format_kind<optional<_Tp>> = range_format::disabled; +#endif // __cpp_lib_optional_range_support + #undef _GLIBCXX_USE_CONSTRAINTS_FOR_OPTIONAL _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 9300c36..3a6710b 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -660,7 +660,7 @@ namespace ranges : _M_value(__value) { } - constexpr + constexpr explicit iota_view(type_identity_t<_Winc> __value, type_identity_t<_Bound> __bound) : _M_value(__value), _M_bound(__bound) @@ -669,19 +669,19 @@ namespace ranges __glibcxx_assert( bool(__value <= __bound) ); } - constexpr + constexpr explicit iota_view(_Iterator __first, _Iterator __last) requires same_as<_Winc, _Bound> : iota_view(__first._M_value, __last._M_value) { } - constexpr + constexpr explicit iota_view(_Iterator __first, unreachable_sentinel_t __last) requires same_as<_Bound, unreachable_sentinel_t> : iota_view(__first._M_value, __last) { } - constexpr + constexpr explicit iota_view(_Iterator __first, _Sentinel __last) requires (!same_as<_Winc, _Bound>) && (!same_as<_Bound, unreachable_sentinel_t>) : iota_view(__first._M_value, __last._M_bound) @@ -1811,7 +1811,7 @@ namespace views::__adaptor && default_initializable<_Pred>) = default; - constexpr + constexpr explicit filter_view(_Vp __base, _Pred __pred) : _M_base(std::move(__base)), _M_pred(std::move(__pred)) { } @@ -2188,7 +2188,7 @@ namespace views::__adaptor && default_initializable<_Fp>) = default; - constexpr + constexpr explicit transform_view(_Vp __base, _Fp __fun) : _M_base(std::move(__base)), _M_fun(std::move(__fun)) { } @@ -2323,7 +2323,7 @@ namespace views::__adaptor public: take_view() requires default_initializable<_Vp> = default; - constexpr + constexpr explicit take_view(_Vp __base, range_difference_t<_Vp> __count) : _M_base(std::move(__base)), _M_count(std::move(__count)) { } @@ -2562,7 +2562,7 @@ namespace views::__adaptor && default_initializable<_Pred>) = default; - constexpr + constexpr explicit take_while_view(_Vp __base, _Pred __pred) : _M_base(std::move(__base)), _M_pred(std::move(__pred)) { } @@ -2650,7 +2650,7 @@ namespace views::__adaptor public: drop_view() requires default_initializable<_Vp> = default; - constexpr + constexpr explicit drop_view(_Vp __base, range_difference_t<_Vp> __count) : _M_base(std::move(__base)), _M_count(__count) { __glibcxx_assert(__count >= 0); } @@ -2804,7 +2804,7 @@ namespace views::__adaptor && default_initializable<_Pred>) = default; - constexpr + constexpr explicit drop_while_view(_Vp __base, _Pred __pred) : _M_base(std::move(__base)), _M_pred(std::move(__pred)) { } @@ -3641,7 +3641,7 @@ namespace views::__adaptor && default_initializable<_Pattern>) = default; - constexpr + constexpr explicit lazy_split_view(_Vp __base, _Pattern __pattern) : _M_base(std::move(__base)), _M_pattern(std::move(__pattern)) { } @@ -3649,7 +3649,7 @@ namespace views::__adaptor template<input_range _Range> requires constructible_from<_Vp, views::all_t<_Range>> && constructible_from<_Pattern, single_view<range_value_t<_Range>>> - constexpr + constexpr explicit lazy_split_view(_Range&& __r, range_value_t<_Range> __e) : _M_base(views::all(std::forward<_Range>(__r))), _M_pattern(views::single(std::move(__e))) @@ -3766,7 +3766,7 @@ namespace views::__adaptor && default_initializable<_Pattern>) = default; - constexpr + constexpr explicit split_view(_Vp __base, _Pattern __pattern) : _M_base(std::move(__base)), _M_pattern(std::move(__pattern)) { } @@ -3774,7 +3774,7 @@ namespace views::__adaptor template<forward_range _Range> requires constructible_from<_Vp, views::all_t<_Range>> && constructible_from<_Pattern, single_view<range_value_t<_Range>>> - constexpr + constexpr explicit split_view(_Range&& __r, range_value_t<_Range> __e) : _M_base(views::all(std::forward<_Range>(__r))), _M_pattern(views::single(std::move(__e))) @@ -5336,7 +5336,7 @@ namespace views::__adaptor requires move_constructible<decay_t<_Fp>> && regular_invocable<decay_t<_Fp>&> && is_object_v<decay_t<invoke_result_t<decay_t<_Fp>&>>> constexpr auto - operator() [[nodiscard]] (_Fp&& __f) const + operator() [[nodiscard]] (_Fp&&) const { return views::empty<decay_t<invoke_result_t<decay_t<_Fp>&>>>; } @@ -6598,7 +6598,7 @@ namespace views::__adaptor } friend constexpr difference_type - operator-(default_sentinel_t __y, const _Iterator& __x) + operator-(default_sentinel_t, const _Iterator& __x) requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>> { return __detail::__div_ceil(__x._M_end - __x._M_current, __x._M_n); } @@ -7287,15 +7287,15 @@ namespace views::__adaptor using iterator_category = decltype(_S_iter_cat()); }; - template<bool> struct _Iterator; - template<bool> struct _Sentinel; + template<bool> class _Iterator; + template<bool> class _Sentinel; public: join_with_view() requires (default_initializable<_Vp> && default_initializable<_Pattern>) = default; - constexpr + constexpr explicit join_with_view(_Vp __base, _Pattern __pattern) : _M_base(std::move(__base)), _M_pattern(std::move(__pattern)) { } @@ -7303,7 +7303,7 @@ namespace views::__adaptor template<input_range _Range> requires constructible_from<_Vp, views::all_t<_Range>> && constructible_from<_Pattern, single_view<range_value_t<_InnerRange>>> - constexpr + constexpr explicit join_with_view(_Range&& __r, range_value_t<_InnerRange> __e) : _M_base(views::all(std::forward<_Range>(__r))), _M_pattern(views::single(std::move(__e))) @@ -7743,7 +7743,7 @@ namespace views::__adaptor __detail::__box<_Tp> _M_value; [[no_unique_address]] _Bound _M_bound = _Bound(); - struct _Iterator; + class _Iterator; template<typename _Range> friend constexpr auto @@ -8303,7 +8303,7 @@ namespace views::__adaptor } friend constexpr difference_type - operator-(default_sentinel_t __y, const _Iterator& __x) + operator-(default_sentinel_t, const _Iterator& __x) requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<_Base>> { return __detail::__div_ceil(__x._M_end - __x._M_current, __x._M_stride); } @@ -9735,7 +9735,7 @@ namespace ranges end() requires (!(__detail::__simple_view<_Vs> && ...)) { constexpr auto __n = sizeof...(_Vs); - if constexpr ((semiregular<iterator_t<_Vs>> && ...) + if constexpr (__detail::__all_forward<false, _Vs...> && common_range<_Vs...[__n - 1]>) return _Iterator<false>(this, in_place_index<__n - 1>, ranges::end(std::get<__n - 1>(_M_views))); @@ -9747,7 +9747,7 @@ namespace ranges end() const requires (range<const _Vs> && ...) && __detail::__concatable<const _Vs...> { constexpr auto __n = sizeof...(_Vs); - if constexpr ((semiregular<iterator_t<const _Vs>> && ...) + if constexpr (__detail::__all_forward<true, _Vs...> && common_range<const _Vs...[__n - 1]>) return _Iterator<true>(this, in_place_index<__n - 1>, ranges::end(std::get<__n - 1>(_M_views))); diff --git a/libstdc++-v3/include/std/semaphore b/libstdc++-v3/include/std/semaphore index bec5ac3..18d0407 100644 --- a/libstdc++-v3/include/std/semaphore +++ b/libstdc++-v3/include/std/semaphore @@ -35,29 +35,28 @@ #include <bits/requires_hosted.h> // concurrency -#if __cplusplus > 201703L -#include <bits/semaphore_base.h> - #define __glibcxx_want_semaphore #include <bits/version.h> -#ifdef __cpp_lib_semaphore // C++ >= 20 && hosted && (atomic_wait || posix_sem) +#ifdef __cpp_lib_semaphore // C++ >= 20 && hosted && atomic_wait +#include <bits/semaphore_base.h> + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION - template<ptrdiff_t __least_max_value = __semaphore_impl::_S_max> + template<ptrdiff_t __least_max_value = _Semaphore_impl<2>::_S_max> class counting_semaphore { static_assert(__least_max_value >= 0); - static_assert(__least_max_value <= __semaphore_impl::_S_max); - __semaphore_impl _M_sem; + _Semaphore_impl<__least_max_value> _M_sem; public: - explicit counting_semaphore(ptrdiff_t __desired) noexcept - : _M_sem(__desired) - { } + constexpr explicit + counting_semaphore(ptrdiff_t __desired) noexcept + : _M_sem(__desired) + { __glibcxx_assert(__desired >= 0 && __desired <= max()); } ~counting_semaphore() = default; @@ -69,8 +68,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __least_max_value; } void - release(ptrdiff_t __update = 1) noexcept(noexcept(_M_sem._M_release(1))) - { _M_sem._M_release(__update); } + release(ptrdiff_t __update = 1) noexcept + { + [[maybe_unused]] ptrdiff_t __old = _M_sem._M_release(__update); + __glibcxx_assert(__update >= 0 && __update <= max() - __old); + } void acquire() noexcept(noexcept(_M_sem._M_acquire())) @@ -91,10 +93,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return _M_sem._M_try_acquire_until(__atime); } }; + /** @brief A binary semaphore + * + * @since C++20 + */ using binary_semaphore = std::counting_semaphore<1>; _GLIBCXX_END_NAMESPACE_VERSION } // namespace -#endif // cpp_lib_atomic_wait || _GLIBCXX_HAVE_POSIX_SEMAPHORE #endif // __cpp_lib_semaphore #endif // _GLIBCXX_SEMAPHORE diff --git a/libstdc++-v3/include/std/sstream b/libstdc++-v3/include/std/sstream index ad0c16a..b1b4126 100644 --- a/libstdc++-v3/include/std/sstream +++ b/libstdc++-v3/include/std/sstream @@ -41,8 +41,16 @@ #include <istream> #include <ostream> + #include <bits/alloc_traits.h> // allocator_traits, __allocator_like +#define __glibcxx_want_sstream_from_string_view +#include <bits/version.h> + +#ifdef __cpp_lib_sstream_from_string_view +# include <string_view> +#endif + #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI # define _GLIBCXX_LVAL_REF_QUAL & # define _GLIBCXX_SSTREAM_ALWAYS_INLINE @@ -52,8 +60,6 @@ # define _GLIBCXX_SSTREAM_ALWAYS_INLINE [[__gnu__::__always_inline__]] #endif - - namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -159,6 +165,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), 0, 0); } #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI + // P0408 Efficient access to basic_stringbuf buffer explicit basic_stringbuf(const allocator_type& __a) : basic_stringbuf(ios_base::in | std::ios_base::out, __a) @@ -197,7 +204,36 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 | ios_base::out) : basic_stringbuf(__s, __mode, allocator_type{}) { } +#endif +#ifdef __cpp_lib_sstream_from_string_view + template<typename _Tp> + explicit + basic_stringbuf(const _Tp& __t, + ios_base::openmode __mode = ios_base::in | ios_base::out) + requires (is_convertible_v<const _Tp&, + basic_string_view<_CharT, _Traits>>) + : basic_stringbuf(__t, __mode, allocator_type{}) + { } + + template<typename _Tp> + basic_stringbuf(const _Tp& __t, const allocator_type& __a) + requires (is_convertible_v<const _Tp&, + basic_string_view<_CharT, _Traits>>) + : basic_stringbuf(__t, ios_base::in | ios_base::out, __a) + { } + + template<typename _Tp> + basic_stringbuf(const _Tp& __t, ios_base::openmode __mode, + const allocator_type& __a) + requires (is_convertible_v<const _Tp&, + basic_string_view<_CharT, _Traits>>) + : _M_string(__t, __a) + { _M_stringbuf_init(__mode); } +#endif // C++26 + +#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI + // P0408 Efficient access to basic_stringbuf buffer basic_stringbuf(basic_stringbuf&& __rhs, const allocator_type& __a) : basic_stringbuf(std::move(__rhs), __a, __xfer_bufptrs(__rhs, this)) { __rhs._M_sync(const_cast<char_type*>(__rhs._M_string.data()), 0, 0); } @@ -262,6 +298,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201703L #if _GLIBCXX_USE_CXX11_ABI #if __cpp_concepts + // P0407 Allocator-aware basic_streambuf template<__allocator_like _SAlloc> _GLIBCXX_NODISCARD basic_string<_CharT, _Traits, _SAlloc> @@ -317,6 +354,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI #if __cpp_concepts + // P0407 Allocator-aware basic_streambuf template<__allocator_like _SAlloc> requires (!is_same_v<_SAlloc, _Alloc>) void @@ -335,6 +373,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 } #endif +#ifdef __cpp_lib_sstream_from_string_view + template <typename _Tp> + void + str(const _Tp& __t) + requires (is_convertible_v<const _Tp&, + basic_string_view<_CharT, _Traits>>) + { + basic_string_view<_CharT, _Traits> __sv{__t}; + _M_string = __sv; + _M_stringbuf_init(_M_mode); + } +#endif // C++26 + protected: // Common initialization code goes here. void @@ -521,6 +572,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { } #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI + // P0408 Efficient access to basic_stringbuf buffer + // The move constructor initializes an __xfer_bufptrs temporary then // delegates to this constructor to performs moves during its lifetime. basic_stringbuf(basic_stringbuf&& __rhs, const allocator_type& __a, @@ -584,7 +637,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ basic_istringstream() : __istream_type(), _M_stringbuf(ios_base::in) - { this->init(&_M_stringbuf); } + { this->init(std::__addressof(_M_stringbuf)); } /** * @brief Starts with an empty string buffer. @@ -601,7 +654,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 explicit basic_istringstream(ios_base::openmode __mode) : __istream_type(), _M_stringbuf(__mode | ios_base::in) - { this->init(&_M_stringbuf); } + { this->init(std::__addressof(_M_stringbuf)); } /** * @brief Starts with an existing string buffer. @@ -620,7 +673,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 basic_istringstream(const __string_type& __str, ios_base::openmode __mode = ios_base::in) : __istream_type(), _M_stringbuf(__str, __mode | ios_base::in) - { this->init(&_M_stringbuf); } + { this->init(std::__addressof(_M_stringbuf)); } /** * @brief The destructor does nothing. @@ -637,9 +690,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 basic_istringstream(basic_istringstream&& __rhs) : __istream_type(std::move(__rhs)), _M_stringbuf(std::move(__rhs._M_stringbuf)) - { __istream_type::set_rdbuf(&_M_stringbuf); } + { __istream_type::set_rdbuf(std::__addressof(_M_stringbuf)); } #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI + // P0408 Efficient access to basic_stringbuf buffer basic_istringstream(ios_base::openmode __mode, const allocator_type& __a) : __istream_type(), _M_stringbuf(__mode | ios_base::in, __a) { this->init(std::__addressof(_M_stringbuf)); } @@ -671,6 +725,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { } #endif // C++20 +#ifdef __cpp_lib_sstream_from_string_view + template <typename _Tp> + explicit + basic_istringstream(const _Tp& __t, + ios_base::openmode __mode = ios_base::in) + requires (is_convertible_v<const _Tp&, + basic_string_view<_CharT, _Traits>>) + : basic_istringstream(__t, __mode, allocator_type{}) + { } + + template <typename _Tp> + basic_istringstream(const _Tp& __t, const allocator_type& __a) + requires (is_convertible_v<const _Tp&, + basic_string_view<_CharT, _Traits>>) + : basic_istringstream(__t, ios_base::in, __a) + { } + + template <typename _Tp> + basic_istringstream(const _Tp& __t, ios_base::openmode __mode, + const allocator_type& __a) + requires (is_convertible_v<const _Tp&, + basic_string_view<_CharT, _Traits>>) + : __istream_type(), _M_stringbuf(__t, __mode | ios_base::in, __a) + { this->init(std::__addressof(_M_stringbuf)); } +#endif // C++26 + // 27.8.3.2 Assign and swap: basic_istringstream& @@ -702,7 +782,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _GLIBCXX_NODISCARD __stringbuf_type* rdbuf() const - { return const_cast<__stringbuf_type*>(&_M_stringbuf); } + { return const_cast<__stringbuf_type*>(std::__addressof(_M_stringbuf)); } /** * @brief Copying out the string buffer. @@ -716,6 +796,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201703L #if _GLIBCXX_USE_CXX11_ABI #if __cpp_concepts + // P0407 Allocator-aware basic_streambuf template<__allocator_like _SAlloc> _GLIBCXX_NODISCARD basic_string<_CharT, _Traits, _SAlloc> @@ -747,6 +828,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI #if __cpp_concepts + // P0407 Allocator-aware basic_streambuf template<__allocator_like _SAlloc> requires (!is_same_v<_SAlloc, _Alloc>) void @@ -758,6 +840,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 str(__string_type&& __s) { _M_stringbuf.str(std::move(__s)); } #endif + +#ifdef __cpp_lib_sstream_from_string_view + template<typename _Tp> + void + str(const _Tp& __t) + requires (is_convertible_v<const _Tp&, + basic_string_view<_CharT, _Traits>>) + { _M_stringbuf.str(__t); } +#endif // C++26 }; @@ -812,7 +903,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ basic_ostringstream() : __ostream_type(), _M_stringbuf(ios_base::out) - { this->init(&_M_stringbuf); } + { this->init(std::__addressof(_M_stringbuf)); } /** * @brief Starts with an empty string buffer. @@ -829,7 +920,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 explicit basic_ostringstream(ios_base::openmode __mode) : __ostream_type(), _M_stringbuf(__mode | ios_base::out) - { this->init(&_M_stringbuf); } + { this->init(std::__addressof(_M_stringbuf)); } /** * @brief Starts with an existing string buffer. @@ -848,7 +939,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 basic_ostringstream(const __string_type& __str, ios_base::openmode __mode = ios_base::out) : __ostream_type(), _M_stringbuf(__str, __mode | ios_base::out) - { this->init(&_M_stringbuf); } + { this->init(std::__addressof(_M_stringbuf)); } /** * @brief The destructor does nothing. @@ -865,9 +956,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 basic_ostringstream(basic_ostringstream&& __rhs) : __ostream_type(std::move(__rhs)), _M_stringbuf(std::move(__rhs._M_stringbuf)) - { __ostream_type::set_rdbuf(&_M_stringbuf); } + { __ostream_type::set_rdbuf(std::__addressof(_M_stringbuf)); } #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI + // P0408 Efficient access to basic_stringbuf buffer basic_ostringstream(ios_base::openmode __mode, const allocator_type& __a) : __ostream_type(), _M_stringbuf(__mode | ios_base::out, __a) { this->init(std::__addressof(_M_stringbuf)); } @@ -899,6 +991,32 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { } #endif // C++20 +#ifdef __cpp_lib_sstream_from_string_view + template <typename _Tp> + explicit + basic_ostringstream( + const _Tp& __t, ios_base::openmode __mode = ios_base::out) + requires (is_convertible_v<const _Tp&, + basic_string_view<_CharT, _Traits>>) + : basic_ostringstream(__t, __mode, allocator_type{}) + { } + + template <typename _Tp> + basic_ostringstream(const _Tp& __t, const allocator_type& __a) + requires (is_convertible_v<const _Tp&, + basic_string_view<_CharT, _Traits>>) + : basic_ostringstream(__t, ios_base::out, __a) + { } + + template <typename _Tp> + basic_ostringstream(const _Tp& __t, ios_base::openmode __mode, + const allocator_type& __a) + requires (is_convertible_v<const _Tp&, + basic_string_view<_CharT, _Traits>>) + : __ostream_type(), _M_stringbuf(__t, __mode | ios_base::out, __a) + { this->init(std::__addressof(_M_stringbuf)); } +#endif // C++26 + // 27.8.3.2 Assign and swap: basic_ostringstream& @@ -930,7 +1048,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _GLIBCXX_NODISCARD __stringbuf_type* rdbuf() const - { return const_cast<__stringbuf_type*>(&_M_stringbuf); } + { return const_cast<__stringbuf_type*>(std::__addressof(_M_stringbuf)); } /** * @brief Copying out the string buffer. @@ -944,6 +1062,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201703L #if _GLIBCXX_USE_CXX11_ABI #if __cpp_concepts + // P0407 Allocator-aware basic_streambuf template<__allocator_like _SAlloc> _GLIBCXX_NODISCARD basic_string<_CharT, _Traits, _SAlloc> @@ -975,6 +1094,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI #if __cpp_concepts + // P0407 Allocator-aware basic_streambuf template<__allocator_like _SAlloc> requires (!is_same_v<_SAlloc, _Alloc>) void @@ -986,6 +1106,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 str(__string_type&& __s) { _M_stringbuf.str(std::move(__s)); } #endif + +#ifdef __cpp_lib_sstream_from_string_view + template<typename _Tp> + void + str(const _Tp& __t) + requires (is_convertible_v<const _Tp&, + basic_string_view<_CharT, _Traits>>) + { _M_stringbuf.str(__t); } +#endif // C++26 }; @@ -1040,7 +1169,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ basic_stringstream() : __iostream_type(), _M_stringbuf(ios_base::out | ios_base::in) - { this->init(&_M_stringbuf); } + { this->init(std::__addressof(_M_stringbuf)); } /** * @brief Starts with an empty string buffer. @@ -1055,7 +1184,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 explicit basic_stringstream(ios_base::openmode __m) : __iostream_type(), _M_stringbuf(__m) - { this->init(&_M_stringbuf); } + { this->init(std::__addressof(_M_stringbuf)); } /** * @brief Starts with an existing string buffer. @@ -1072,7 +1201,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 basic_stringstream(const __string_type& __str, ios_base::openmode __m = ios_base::out | ios_base::in) : __iostream_type(), _M_stringbuf(__str, __m) - { this->init(&_M_stringbuf); } + { this->init(std::__addressof(_M_stringbuf)); } /** * @brief The destructor does nothing. @@ -1089,12 +1218,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 basic_stringstream(basic_stringstream&& __rhs) : __iostream_type(std::move(__rhs)), _M_stringbuf(std::move(__rhs._M_stringbuf)) - { __iostream_type::set_rdbuf(&_M_stringbuf); } + { __iostream_type::set_rdbuf(std::__addressof(_M_stringbuf)); } #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI + // P0408 Efficient access to basic_stringbuf buffer basic_stringstream(ios_base::openmode __mode, const allocator_type& __a) : __iostream_type(), _M_stringbuf(__mode, __a) - { this->init(&_M_stringbuf); } + { this->init(std::__addressof(_M_stringbuf)); } explicit basic_stringstream(__string_type&& __str, @@ -1125,6 +1255,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { } #endif // C++20 +#ifdef __cpp_lib_sstream_from_string_view + template <typename _Tp> + explicit + basic_stringstream(const _Tp& __t, + ios_base::openmode __mode = ios_base::in | ios_base::out) + requires (is_convertible_v<const _Tp&, + basic_string_view<_CharT, _Traits>>) + : basic_stringstream(__t, __mode, allocator_type{}) + { } + + template <typename _Tp> + basic_stringstream(const _Tp& __t, const allocator_type& __a) + requires (is_convertible_v<const _Tp&, + basic_string_view<_CharT, _Traits>>) + : basic_stringstream(__t, ios_base::in | ios_base::out, __a) + { } + + template <typename _Tp> + basic_stringstream(const _Tp& __t, ios_base::openmode __mode, + const allocator_type& __a) + requires (is_convertible_v<const _Tp&, basic_string_view<_CharT, _Traits>>) + : __iostream_type(), _M_stringbuf(__t, __mode, __a) + { this->init(std::__addressof(_M_stringbuf)); } +#endif // C++26 + // 27.8.3.2 Assign and swap: basic_stringstream& @@ -1156,7 +1311,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _GLIBCXX_NODISCARD __stringbuf_type* rdbuf() const - { return const_cast<__stringbuf_type*>(&_M_stringbuf); } + { return const_cast<__stringbuf_type*>(std::__addressof(_M_stringbuf)); } /** * @brief Copying out the string buffer. @@ -1170,6 +1325,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201703L #if _GLIBCXX_USE_CXX11_ABI #if __cpp_concepts + // P0407 Allocator-aware basic_streambuf template<__allocator_like _SAlloc> _GLIBCXX_NODISCARD basic_string<_CharT, _Traits, _SAlloc> @@ -1201,6 +1357,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI #if __cpp_concepts + // P0407 Allocator-aware basic_streambuf template<__allocator_like _SAlloc> requires (!is_same_v<_SAlloc, _Alloc>) void @@ -1212,6 +1369,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 str(__string_type&& __s) { _M_stringbuf.str(std::move(__s)); } #endif + +#ifdef __cpp_lib_sstream_from_string_view + template<typename _Tp> + void + str(const _Tp& __t) + requires (is_convertible_v<const _Tp&, + basic_string_view<_CharT, _Traits>>) + { _M_stringbuf.str(__t); } +#endif // C++26 }; #if __cplusplus >= 201103L diff --git a/libstdc++-v3/include/std/stop_token b/libstdc++-v3/include/std/stop_token index 1225b3a..775ec6a 100644 --- a/libstdc++-v3/include/std/stop_token +++ b/libstdc++-v3/include/std/stop_token @@ -34,8 +34,7 @@ #define __glibcxx_want_jthread #include <bits/version.h> -#if __cplusplus > 201703L - +#ifdef __glibcxx_jthread // C++ >= 20 #include <atomic> #include <bits/std_thread.h> @@ -650,6 +649,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION stop_callback(stop_token, _Callback) -> stop_callback<_Callback>; _GLIBCXX_END_NAMESPACE_VERSION -} // namespace -#endif // __cplusplus > 201703L +} // namespace std +#endif // __glibcxx_jthread #endif // _GLIBCXX_STOP_TOKEN diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 2e69af1..b39ce71 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -2939,19 +2939,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif #ifdef __cpp_lib_make_from_tuple // C++ >= 17 + template <typename _Tp, typename _Tuple, typename _Seq + = make_index_sequence<tuple_size_v<remove_reference_t<_Tuple>>>> + constexpr bool __can_make_from_tuple = false; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3528. make_from_tuple can perform (the equivalent of) a C-style cast + template <typename _Tp, typename _Tuple, size_t... _Idx> + constexpr bool __can_make_from_tuple<_Tp, _Tuple, index_sequence<_Idx...>> + = is_constructible_v<_Tp, + decltype(std::get<_Idx>(std::declval<_Tuple>()))...>; + template <typename _Tp, typename _Tuple, size_t... _Idx> constexpr _Tp __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>) - { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); } + { + static_assert(__can_make_from_tuple<_Tp, _Tuple, index_sequence<_Idx...>>); + return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); + } #if __cpp_lib_tuple_like // >= C++23 template <typename _Tp, __tuple_like _Tuple> #else template <typename _Tp, typename _Tuple> #endif - constexpr _Tp + constexpr auto make_from_tuple(_Tuple&& __t) noexcept(__unpack_std_tuple<is_nothrow_constructible, _Tp, _Tuple>) +#ifdef __cpp_concepts // >= C++20 + -> _Tp + requires __can_make_from_tuple<_Tp, _Tuple> +#else + -> __enable_if_t<__can_make_from_tuple<_Tp, _Tuple>, _Tp> +#endif { constexpr size_t __n = tuple_size_v<remove_reference_t<_Tuple>>; #if __has_builtin(__reference_constructs_from_temporary) diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index 676cdf2..0554111 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -280,11 +280,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Forward declarations template<typename> - struct is_reference; - template<typename> - struct is_function; - template<typename> - struct is_void; + struct is_object; template<typename> struct remove_cv; template<typename> @@ -294,21 +290,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename> struct __is_array_unknown_bounds; + // An object type which is not an unbounded array. + // It might still be an incomplete type, but if this is false_type + // then we can be certain it's not a complete object type. + template<typename _Tp> + using __maybe_complete_object_type + = __and_<is_object<_Tp>, __not_<__is_array_unknown_bounds<_Tp>>>; + // Helper functions that return false_type for incomplete classes, // incomplete unions and arrays of known bound from those. - template <typename _Tp, size_t = sizeof(_Tp)> - constexpr true_type __is_complete_or_unbounded(__type_identity<_Tp>) - { return {}; } - - template <typename _TypeIdentity, - typename _NestedType = typename _TypeIdentity::type> - constexpr typename __or_< - is_reference<_NestedType>, - is_function<_NestedType>, - is_void<_NestedType>, - __is_array_unknown_bounds<_NestedType> - >::type __is_complete_or_unbounded(_TypeIdentity) + // More specialized overload for complete object types (returning true_type). + template<typename _Tp, + typename = __enable_if_t<__maybe_complete_object_type<_Tp>::value>, + size_t = sizeof(_Tp)> + constexpr true_type + __is_complete_or_unbounded(__type_identity<_Tp>) + { return {}; }; + + // Less specialized overload for reference and unknown-bound array types + // (returning true_type), and incomplete types (returning false_type). + template<typename _TypeIdentity, + typename _NestedType = typename _TypeIdentity::type> + constexpr typename __not_<__maybe_complete_object_type<_NestedType>>::type + __is_complete_or_unbounded(_TypeIdentity) { return {}; } // __remove_cv_t (std::remove_cv_t for C++11). @@ -1036,9 +1041,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __is_array_unknown_bounds<_Tp[]> : public true_type { }; + /// @endcond // Destructible and constructible type properties. +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_destructible) + /// is_destructible + template<typename _Tp> + struct is_destructible + : public __bool_constant<__is_destructible(_Tp)> + { }; +#else + /// @cond undocumented + // In N3290 is_destructible does not say anything about function // types and abstract types, see LWG 2049. This implementation // describes function types as non-destructible and all complete @@ -1090,7 +1105,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; +#endif +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_destructible) + /// is_nothrow_destructible + template<typename _Tp> + struct is_nothrow_destructible + : public __bool_constant<__is_nothrow_destructible(_Tp)> + { }; +#else /// @cond undocumented // is_nothrow_destructible requires that is_destructible is @@ -1144,6 +1167,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; +#endif /// @cond undocumented template<typename _Tp, typename... _Args> @@ -1451,6 +1475,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION "template argument must be a complete class or an unbounded array"); }; +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_trivially_destructible) + /// is_trivially_destructible + template<typename _Tp> + struct is_trivially_destructible + : public __bool_constant<__is_trivially_destructible(_Tp)> + { }; +#else /// is_trivially_destructible template<typename _Tp> struct is_trivially_destructible @@ -1460,7 +1491,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), "template argument must be a complete class or an unbounded array"); }; - +#endif /// has_virtual_destructor template<typename _Tp> @@ -3212,7 +3243,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Fn, typename... _ArgTypes> struct __is_invocable +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_invocable) + : __bool_constant<__is_invocable(_Fn, _ArgTypes...)> +#else : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type +#endif { }; template<typename _Fn, typename _Tp, typename... _Args> @@ -3263,8 +3298,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // __is_nothrow_invocable (std::is_nothrow_invocable for C++11) template<typename _Fn, typename... _Args> struct __is_nothrow_invocable +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_invocable) + : __bool_constant<__is_nothrow_invocable(_Fn, _Args...)> +#else : __and_<__is_invocable<_Fn, _Args...>, __call_is_nothrow_<_Fn, _Args...>>::type +#endif { }; #pragma GCC diagnostic push @@ -3573,8 +3612,13 @@ template <typename _Tp> inline constexpr bool is_move_assignable_v = __is_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>); +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_destructible) +template <typename _Tp> + inline constexpr bool is_destructible_v = __is_destructible(_Tp); +#else template <typename _Tp> inline constexpr bool is_destructible_v = is_destructible<_Tp>::value; +#endif template <typename _Tp, typename... _Args> inline constexpr bool is_trivially_constructible_v @@ -3601,7 +3645,11 @@ template <typename _Tp> = __is_trivially_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>); -#if __cpp_concepts +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_trivially_destructible) +template <typename _Tp> + inline constexpr bool is_trivially_destructible_v + = __is_trivially_destructible(_Tp); +#elif __cpp_concepts template <typename _Tp> inline constexpr bool is_trivially_destructible_v = false; @@ -3646,9 +3694,15 @@ template <typename _Tp> inline constexpr bool is_nothrow_move_assignable_v = __is_nothrow_assignable(__add_lval_ref_t<_Tp>, __add_rval_ref_t<_Tp>); +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_destructible) +template <typename _Tp> + inline constexpr bool is_nothrow_destructible_v + = __is_nothrow_destructible(_Tp); +#else template <typename _Tp> inline constexpr bool is_nothrow_destructible_v = is_nothrow_destructible<_Tp>::value; +#endif template <typename _Tp> inline constexpr bool has_virtual_destructor_v @@ -3704,10 +3758,19 @@ template <typename _From, typename _To> inline constexpr bool is_convertible_v = is_convertible<_From, _To>::value; #endif template<typename _Fn, typename... _Args> - inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value; + inline constexpr bool is_invocable_v +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_invocable) + = __is_invocable(_Fn, _Args...); +#else + = is_invocable<_Fn, _Args...>::value; +#endif template<typename _Fn, typename... _Args> inline constexpr bool is_nothrow_invocable_v +#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_nothrow_invocable) + = __is_nothrow_invocable(_Fn, _Args...); +#else = is_nothrow_invocable<_Fn, _Args...>::value; +#endif template<typename _Ret, typename _Fn, typename... _Args> inline constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value; @@ -4002,7 +4065,8 @@ template<typename _Ret, typename _Fn, typename... _Args> #ifdef __cpp_lib_is_constant_evaluated // C++ >= 20 && HAVE_IS_CONST_EVAL /// Returns true only when called during constant evaluation. /// @since C++20 - constexpr inline bool + [[__gnu__::__always_inline__]] + constexpr bool is_constant_evaluated() noexcept { #if __cpp_if_consteval >= 202106L diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility index 1c15c75..8a85ccf 100644 --- a/libstdc++-v3/include/std/utility +++ b/libstdc++-v3/include/std/utility @@ -201,7 +201,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #ifdef __cpp_lib_to_underlying // C++ >= 23 /// Convert an object of enumeration type to its underlying type. template<typename _Tp> - [[nodiscard]] + [[nodiscard, __gnu__::__always_inline__]] constexpr underlying_type_t<_Tp> to_underlying(_Tp __value) noexcept { return static_cast<underlying_type_t<_Tp>>(__value); } |