diff options
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r-- | libstdc++-v3/include/bits/formatfwd.h | 95 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/stl_queue.h | 14 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/stl_stack.h | 9 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/stl_tree.h | 106 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/version.def | 3 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/version.h | 3 | ||||
-rw-r--r-- | libstdc++-v3/include/std/format | 333 | ||||
-rw-r--r-- | libstdc++-v3/include/std/future | 66 | ||||
-rw-r--r-- | libstdc++-v3/include/std/queue | 80 | ||||
-rw-r--r-- | libstdc++-v3/include/std/stack | 48 | ||||
-rw-r--r-- | libstdc++-v3/include/std/thread | 45 |
11 files changed, 493 insertions, 309 deletions
diff --git a/libstdc++-v3/include/bits/formatfwd.h b/libstdc++-v3/include/bits/formatfwd.h index a6b5ac8..12ae2ad 100644 --- a/libstdc++-v3/include/bits/formatfwd.h +++ b/libstdc++-v3/include/bits/formatfwd.h @@ -37,6 +37,12 @@ // <bits/version.h> must have been included before this header: #ifdef __glibcxx_format // C++ >= 20 && HOSTED +#include <concepts> +#include <type_traits> +#if __glibcxx_format_ranges // C++ >= 23 && HOSTED +# include <bits/ranges_base.h> // input_range, range_reference_t +#endif + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -50,6 +56,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // [format.formatter], formatter template<typename _Tp, typename _CharT = char> struct formatter; +/// @cond undocumented + [[noreturn]] + inline void + __throw_format_error(const char* __what); + namespace __format { #ifdef _GLIBCXX_USE_WCHAR_T @@ -60,9 +71,89 @@ namespace __format concept __char = same_as<_CharT, char>; #endif - template<__char _CharT> - struct __formatter_int; + enum _Align { + _Align_default, + _Align_left, + _Align_right, + _Align_centre, + }; + + template<typename _CharT> struct _Spec; + + template<__char _CharT> struct __formatter_str; + template<__char _CharT> struct __formatter_int; + template<__char _CharT> struct __formatter_ptr; + + template<typename _Tp, typename _Context, + typename _Formatter + = typename _Context::template formatter_type<remove_const_t<_Tp>>, + typename _ParseContext + = basic_format_parse_context<typename _Context::char_type>> + concept __parsable_with + = semiregular<_Formatter> + && requires (_Formatter __f, _ParseContext __pc) + { + { __f.parse(__pc) } -> same_as<typename _ParseContext::iterator>; + }; + + template<typename _Tp, typename _Context, + typename _Formatter + = typename _Context::template formatter_type<remove_const_t<_Tp>>, + typename _ParseContext + = basic_format_parse_context<typename _Context::char_type>> + concept __formattable_with + = semiregular<_Formatter> + && requires (const _Formatter __cf, _Tp&& __t, _Context __fc) + { + { __cf.format(__t, __fc) } -> same_as<typename _Context::iterator>; + }; + + // An unspecified output iterator type used in the `formattable` concept. + template<typename _CharT> + struct _Iter_for; + template<typename _CharT> + using _Iter_for_t = typename _Iter_for<_CharT>::type; + + template<typename _Tp, typename _CharT, + typename _Context = basic_format_context<_Iter_for_t<_CharT>, _CharT>> + concept __formattable_impl + = __parsable_with<_Tp, _Context> && __formattable_with<_Tp, _Context>; + + template<typename _Formatter> + concept __has_debug_format = requires(_Formatter __f) + { + __f.set_debug_format(); + }; +} // namespace __format +/// @endcond + +#if __glibcxx_format_ranges // C++ >= 23 && HOSTED + // [format.formattable], concept formattable + template<typename _Tp, typename _CharT> + concept formattable + = __format::__formattable_impl<remove_reference_t<_Tp>, _CharT>; + + template<typename _Tp, __format::__char _CharT = char> + requires same_as<remove_cvref_t<_Tp>, _Tp> && formattable<_Tp, _CharT> + class range_formatter; + +/// @cond undocumented +namespace __format +{ + template<typename _Rg, typename _CharT> + concept __const_formattable_range + = ranges::input_range<const _Rg> + && formattable<ranges::range_reference_t<const _Rg>, _CharT>; + + template<typename _Rg, typename _CharT> + using __maybe_const_range + = __conditional_t<__const_formattable_range<_Rg, _CharT>, const _Rg, _Rg>; + + template<typename _Tp, typename _CharT> + using __maybe_const + = __conditional_t<formattable<const _Tp, _CharT>, const _Tp, _Tp>; } +#endif // format_ranges _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/stl_queue.h b/libstdc++-v3/include/bits/stl_queue.h index 554e076..a3a8bc1 100644 --- a/libstdc++-v3/include/bits/stl_queue.h +++ b/libstdc++-v3/include/bits/stl_queue.h @@ -70,6 +70,10 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION +#if __glibcxx_format_ranges + template<typename, typename> class formatter; +#endif + /** * @brief A standard container giving FIFO behavior. * @@ -369,6 +373,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION swap(c, __q.c); } #endif // __cplusplus >= 201103L + +#if __glibcxx_format_ranges + friend class formatter<queue<_Tp, _Sequence>, char>; + friend class formatter<queue<_Tp, _Sequence>, wchar_t>; +#endif }; #if __cpp_deduction_guides >= 201606 @@ -898,6 +907,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION swap(comp, __pq.comp); } #endif // __cplusplus >= 201103L + +#if __glibcxx_format_ranges + friend class formatter<priority_queue<_Tp, _Sequence, _Compare>, char>; + friend class formatter<priority_queue<_Tp, _Sequence, _Compare>, wchar_t>; +#endif }; #if __cpp_deduction_guides >= 201606 diff --git a/libstdc++-v3/include/bits/stl_stack.h b/libstdc++-v3/include/bits/stl_stack.h index 7b32464..27c79d6 100644 --- a/libstdc++-v3/include/bits/stl_stack.h +++ b/libstdc++-v3/include/bits/stl_stack.h @@ -70,6 +70,10 @@ namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION +#if __glibcxx_format_ranges + template<typename, typename> class formatter; +#endif + /** * @brief A standard container giving FILO behavior. * @@ -343,6 +347,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION swap(c, __s.c); } #endif // __cplusplus >= 201103L + +#if __glibcxx_format_ranges + friend class formatter<stack<_Tp, _Sequence>, char>; + friend class formatter<stack<_Tp, _Sequence>, wchar_t>; +#endif }; #if __cpp_deduction_guides >= 201606 diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h index 6b35f99..6caf937 100644 --- a/libstdc++-v3/include/bits/stl_tree.h +++ b/libstdc++-v3/include/bits/stl_tree.h @@ -1390,27 +1390,25 @@ namespace __rb_tree _M_end() const _GLIBCXX_NOEXCEPT { return this->_M_impl._M_header._M_base_ptr(); } - static const _Key& - _S_key(const _Node& __node) - { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2542. Missing const requirements for associative containers + template<typename _Key1, typename _Key2> + bool + _M_key_compare(const _Key1& __k1, const _Key2& __k2) const + { #if __cplusplus >= 201103L - // If we're asking for the key we're presumably using the comparison - // object, and so this is a good place to sanity check it. - static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{}, - "comparison object must be invocable " - "with two arguments of key type"); -# if __cplusplus >= 201703L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2542. Missing const requirements for associative containers - if constexpr (__is_invocable<_Compare&, const _Key&, const _Key&>{}) + // Enforce this here with a user-friendly message. static_assert( - is_invocable_v<const _Compare&, const _Key&, const _Key&>, - "comparison object must be invocable as const"); -# endif // C++17 -#endif // C++11 + __is_invocable<const _Compare&, const _Key&, const _Key&>::value, + "comparison object must be invocable with two arguments of key type" + ); +#endif + return _M_impl._M_key_compare(__k1, __k2); + } - return _KeyOfValue()(*__node._M_valptr()); - } + static const _Key& + _S_key(const _Node& __node) + { return _KeyOfValue()(*__node._M_valptr()); } static const _Key& _S_key(_Base_ptr __x) @@ -1933,7 +1931,7 @@ namespace __rb_tree _M_find_tr(const _Kt& __k) const { const_iterator __j(_M_lower_bound_tr(__k)); - if (__j != end() && _M_impl._M_key_compare(__k, _S_key(__j._M_node))) + if (__j != end() && _M_key_compare(__k, _S_key(__j._M_node))) __j = end(); return __j; } @@ -1955,7 +1953,7 @@ namespace __rb_tree auto __x = _M_begin(); auto __y = _M_end(); while (__x) - if (!_M_impl._M_key_compare(_S_key(__x), __k)) + if (!_M_key_compare(_S_key(__x), __k)) { __y = __x; __x = _S_left(__x); @@ -1973,7 +1971,7 @@ namespace __rb_tree auto __x = _M_begin(); auto __y = _M_end(); while (__x) - if (_M_impl._M_key_compare(__k, _S_key(__x))) + if (_M_key_compare(__k, _S_key(__x))) { __y = __x; __x = _S_left(__x); @@ -2474,8 +2472,8 @@ namespace __rb_tree _NodeGen& __node_gen) { bool __insert_left = (__x || __p == _M_end() - || _M_impl._M_key_compare(_KeyOfValue()(__v), - _S_key(__p))); + || _M_key_compare(_KeyOfValue()(__v), + _S_key(__p))); _Base_ptr __z = __node_gen(_GLIBCXX_FORWARD(_Arg, __v))->_M_base_ptr(); @@ -2500,8 +2498,8 @@ namespace __rb_tree #endif { bool __insert_left = (__p == _M_end() - || !_M_impl._M_key_compare(_S_key(__p), - _KeyOfValue()(__v))); + || !_M_key_compare(_S_key(__p), + _KeyOfValue()(__v))); _Base_ptr __z = _M_create_node(_GLIBCXX_FORWARD(_Arg, __v))->_M_base_ptr(); @@ -2529,7 +2527,7 @@ namespace __rb_tree while (__x) { __y = __x; - __x = !_M_impl._M_key_compare(_S_key(__x), _KeyOfValue()(__v)) ? + __x = !_M_key_compare(_S_key(__x), _KeyOfValue()(__v)) ? _S_left(__x) : _S_right(__x); } return _M_insert_lower(__y, _GLIBCXX_FORWARD(_Arg, __v)); @@ -2601,7 +2599,7 @@ namespace __rb_tree const _Key& __k) const { while (__x) - if (!_M_impl._M_key_compare(_S_key(__x), __k)) + if (!_M_key_compare(_S_key(__x), __k)) __y = __x, __x = _S_left(__x); else __x = _S_right(__x); @@ -2617,7 +2615,7 @@ namespace __rb_tree const _Key& __k) const { while (__x) - if (_M_impl._M_key_compare(__k, _S_key(__x))) + if (_M_key_compare(__k, _S_key(__x))) __y = __x, __x = _S_left(__x); else __x = _S_right(__x); @@ -2639,9 +2637,9 @@ namespace __rb_tree _Base_ptr __y = _M_end(); while (__x) { - if (_M_impl._M_key_compare(_S_key(__x), __k)) + if (_M_key_compare(_S_key(__x), __k)) __x = _S_right(__x); - else if (_M_impl._M_key_compare(__k, _S_key(__x))) + else if (_M_key_compare(__k, _S_key(__x))) __y = __x, __x = _S_left(__x); else { @@ -2671,9 +2669,9 @@ namespace __rb_tree _Base_ptr __y = _M_end(); while (__x) { - if (_M_impl._M_key_compare(_S_key(__x), __k)) + if (_M_key_compare(_S_key(__x), __k)) __x = _S_right(__x); - else if (_M_impl._M_key_compare(__k, _S_key(__x))) + else if (_M_key_compare(__k, _S_key(__x))) __y = __x, __x = _S_left(__x); else { @@ -2737,7 +2735,7 @@ namespace __rb_tree while (__x) { __y = __x; - __comp = _M_impl._M_key_compare(__k, _S_key(__x)); + __comp = _M_key_compare(__k, _S_key(__x)); __x = __comp ? _S_left(__x) : _S_right(__x); } iterator __j = iterator(__y); @@ -2748,7 +2746,7 @@ namespace __rb_tree else --__j; } - if (_M_impl._M_key_compare(_S_key(__j._M_node), __k)) + if (_M_key_compare(_S_key(__j._M_node), __k)) return _Res(__x, __y); return _Res(__j._M_node, _Base_ptr()); } @@ -2768,8 +2766,7 @@ namespace __rb_tree while (__x) { __y = __x; - __x = _M_impl._M_key_compare(__k, _S_key(__x)) ? - _S_left(__x) : _S_right(__x); + __x = _M_key_compare(__k, _S_key(__x)) ? _S_left(__x) : _S_right(__x); } return _Res(__x, __y); } @@ -2838,19 +2835,18 @@ namespace __rb_tree // end() if (__position._M_node == _M_end()) { - if (size() > 0 - && _M_impl._M_key_compare(_S_key(_M_rightmost()), __k)) + if (size() > 0 && _M_key_compare(_S_key(_M_rightmost()), __k)) return _Res(_Base_ptr(), _M_rightmost()); else return _M_get_insert_unique_pos(__k); } - else if (_M_impl._M_key_compare(__k, _S_key(__position._M_node))) + else if (_M_key_compare(__k, _S_key(__position._M_node))) { // First, try before... iterator __before(__position._M_node); if (__position._M_node == _M_leftmost()) // begin() return _Res(_M_leftmost(), _M_leftmost()); - else if (_M_impl._M_key_compare(_S_key((--__before)._M_node), __k)) + else if (_M_key_compare(_S_key((--__before)._M_node), __k)) { if (!_S_right(__before._M_node)) return _Res(_Base_ptr(), __before._M_node); @@ -2860,13 +2856,13 @@ namespace __rb_tree else return _M_get_insert_unique_pos(__k); } - else if (_M_impl._M_key_compare(_S_key(__position._M_node), __k)) + else if (_M_key_compare(_S_key(__position._M_node), __k)) { // ... then try after. iterator __after(__position._M_node); if (__position._M_node == _M_rightmost()) return _Res(_Base_ptr(), _M_rightmost()); - else if (_M_impl._M_key_compare(__k, _S_key((++__after)._M_node))) + else if (_M_key_compare(__k, _S_key((++__after)._M_node))) { if (!_S_right(__position._M_node)) return _Res(_Base_ptr(), __position._M_node); @@ -2923,18 +2919,18 @@ namespace __rb_tree if (__position._M_node == _M_end()) { if (size() > 0 - && !_M_impl._M_key_compare(__k, _S_key(_M_rightmost()))) + && !_M_key_compare(__k, _S_key(_M_rightmost()))) return _Res(_Base_ptr(), _M_rightmost()); else return _M_get_insert_equal_pos(__k); } - else if (!_M_impl._M_key_compare(_S_key(__position._M_node), __k)) + else if (!_M_key_compare(_S_key(__position._M_node), __k)) { // First, try before... iterator __before(__position._M_node); if (__position._M_node == _M_leftmost()) // begin() return _Res(_M_leftmost(), _M_leftmost()); - else if (!_M_impl._M_key_compare(__k, _S_key((--__before)._M_node))) + else if (!_M_key_compare(__k, _S_key((--__before)._M_node))) { if (!_S_right(__before._M_node)) return _Res(_Base_ptr(), __before._M_node); @@ -2950,7 +2946,7 @@ namespace __rb_tree iterator __after(__position._M_node); if (__position._M_node == _M_rightmost()) return _Res(_Base_ptr(), _M_rightmost()); - else if (!_M_impl._M_key_compare(_S_key((++__after)._M_node), __k)) + else if (!_M_key_compare(_S_key((++__after)._M_node), __k)) { if (!_S_right(__position._M_node)) return _Res(_Base_ptr(), __position._M_node); @@ -2999,8 +2995,7 @@ namespace __rb_tree -> iterator { bool __insert_left = (__x || __p == _M_end() - || _M_impl._M_key_compare(_S_key(__z), - _S_key(__p))); + || _M_key_compare(_S_key(__z), _S_key(__p))); _Base_ptr __base_z = __z->_M_base_ptr(); _Node_traits::_S_insert_and_rebalance @@ -3017,8 +3012,7 @@ namespace __rb_tree -> iterator { bool __insert_left = (__p == _M_end() - || !_M_impl._M_key_compare(_S_key(__p), - _S_key(__z))); + || !_M_key_compare(_S_key(__p), _S_key(__z))); _Base_ptr __base_z = __z->_M_base_ptr(); _Node_traits::_S_insert_and_rebalance @@ -3039,7 +3033,7 @@ namespace __rb_tree while (__x) { __y = __x; - __x = !_M_impl._M_key_compare(_S_key(__x), _S_key(__z)) ? + __x = !_M_key_compare(_S_key(__x), _S_key(__z)) ? _S_left(__x) : _S_right(__x); } return _M_insert_lower_node(__y, __z); @@ -3151,8 +3145,7 @@ namespace __rb_tree { iterator __j(_M_lower_bound(_M_begin(), _M_end(), __k)); return (__j == end() - || _M_impl._M_key_compare(__k, - _S_key(__j._M_node))) ? end() : __j; + || _M_key_compare(__k, _S_key(__j._M_node))) ? end() : __j; } template<typename _Key, typename _Val, typename _KeyOfValue, @@ -3164,8 +3157,7 @@ namespace __rb_tree { const_iterator __j(_M_lower_bound(_M_begin(), _M_end(), __k)); return (__j == end() - || _M_impl._M_key_compare(__k, - _S_key(__j._M_node))) ? end() : __j; + || _M_key_compare(__k, _S_key(__j._M_node))) ? end() : __j; } template<typename _Key, typename _Val, typename _KeyOfValue, @@ -3205,9 +3197,9 @@ namespace __rb_tree || (__R && __R->_M_color == _S_red)) return false; - if (__L && _M_impl._M_key_compare(_S_key(__x), _S_key(__L))) + if (__L && _M_key_compare(_S_key(__x), _S_key(__L))) return false; - if (__R && _M_impl._M_key_compare(_S_key(__R), _S_key(__x))) + if (__R && _M_key_compare(_S_key(__R), _S_key(__x))) return false; if (!__L && !__R && _Rb_tree_black_count(__x, _M_root()) != __len) diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 0afaf0d..737b3f4 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -1416,9 +1416,8 @@ ftms = { // 202207 P2286R8 Formatting Ranges // 202207 P2585R1 Improving default container formatting // LWG3750 Too many papers bump __cpp_lib_format - no_stdname = true; // TODO remove values = { - v = 1; // TODO 202207 + v = 202207; cxxmin = 23; hosted = yes; }; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 980fee6..59ff0ce 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -1562,8 +1562,9 @@ #if !defined(__cpp_lib_format_ranges) # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED -# define __glibcxx_format_ranges 1L +# define __glibcxx_format_ranges 202207L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_format_ranges) +# define __cpp_lib_format_ranges 202207L # endif # endif #endif /* !defined(__cpp_lib_format_ranges) && defined(__glibcxx_want_format_ranges) */ diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index e557e10..86c93f0 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -117,6 +117,11 @@ namespace __format template<typename _CharT> class _Sink_iter; + // An unspecified output iterator type used in the `formattable` concept. + template<typename _CharT> + struct _Iter_for + { using type = back_insert_iterator<basic_string<_CharT>>; }; + template<typename _CharT> using __format_context = basic_format_context<_Sink_iter<_CharT>, _CharT>; @@ -135,6 +140,7 @@ namespace __format template<typename, typename...> friend struct std::basic_format_string; }; + } // namespace __format /// @endcond @@ -485,13 +491,6 @@ namespace __format _Pres_esc = 0xf, // For strings, charT and ranges }; - enum _Align { - _Align_default, - _Align_left, - _Align_right, - _Align_centre, - }; - enum _Sign { _Sign_default, _Sign_plus, @@ -1434,6 +1433,13 @@ namespace __format static constexpr _Pres_type _AsBool = _Pres_s; static constexpr _Pres_type _AsChar = _Pres_c; + __formatter_int() = default; + + constexpr + __formatter_int(_Spec<_CharT> __spec) noexcept + : _M_spec(__spec) + { } + constexpr typename basic_format_parse_context<_CharT>::iterator _M_do_parse(basic_format_parse_context<_CharT>& __pc, _Pres_type __type) { @@ -2381,6 +2387,134 @@ namespace __format _Spec<_CharT> _M_spec{}; }; + template<__format::__char _CharT> + struct __formatter_ptr + { + __formatter_ptr() = default; + + constexpr + __formatter_ptr(_Spec<_CharT> __spec) noexcept + : _M_spec(__spec) + { } + + constexpr typename basic_format_parse_context<_CharT>::iterator + parse(basic_format_parse_context<_CharT>& __pc) + { + __format::_Spec<_CharT> __spec{}; + const auto __last = __pc.end(); + auto __first = __pc.begin(); + + auto __finalize = [this, &__spec] { + _M_spec = __spec; + }; + + auto __finished = [&] { + if (__first == __last || *__first == '}') + { + __finalize(); + return true; + } + return false; + }; + + if (__finished()) + return __first; + + __first = __spec._M_parse_fill_and_align(__first, __last); + if (__finished()) + return __first; + +// _GLIBCXX_RESOLVE_LIB_DEFECTS +// P2510R3 Formatting pointers +#if __glibcxx_format >= 202304L + __first = __spec._M_parse_zero_fill(__first, __last); + if (__finished()) + return __first; +#endif + + __first = __spec._M_parse_width(__first, __last, __pc); + + if (__first != __last) + { + if (*__first == 'p') + ++__first; +#if __glibcxx_format >= 202304L + else if (*__first == 'P') + { + __spec._M_type = __format::_Pres_P; + ++__first; + } +#endif + } + + if (__finished()) + return __first; + + __format::__failed_to_parse_format_spec(); + } + + template<typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + format(const void* __v, basic_format_context<_Out, _CharT>& __fc) const + { + auto __u = reinterpret_cast<__UINTPTR_TYPE__>(__v); + char __buf[2 + sizeof(__v) * 2]; + auto [__ptr, __ec] = std::to_chars(__buf + 2, std::end(__buf), + __u, 16); + int __n = __ptr - __buf; + __buf[0] = '0'; + __buf[1] = 'x'; +#if __glibcxx_format >= 202304L + if (_M_spec._M_type == __format::_Pres_P) + { + __buf[1] = 'X'; + for (auto __p = __buf + 2; __p != __ptr; ++__p) +#if __has_builtin(__builtin_toupper) + *__p = __builtin_toupper(*__p); +#else + *__p = std::toupper(*__p); +#endif + } +#endif + + basic_string_view<_CharT> __str; + if constexpr (is_same_v<_CharT, char>) + __str = string_view(__buf, __n); +#ifdef _GLIBCXX_USE_WCHAR_T + else + { + auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT)); + std::__to_wstring_numeric(__buf, __n, __p); + __str = wstring_view(__p, __n); + } +#endif + +#if __glibcxx_format >= 202304L + if (_M_spec._M_zero_fill) + { + size_t __width = _M_spec._M_get_width(__fc); + if (__width <= __str.size()) + return __format::__write(__fc.out(), __str); + + auto __out = __fc.out(); + // Write "0x" or "0X" prefix before zero-filling. + __out = __format::__write(std::move(__out), __str.substr(0, 2)); + __str.remove_prefix(2); + size_t __nfill = __width - __n; + return __format::__write_padded(std::move(__out), __str, + __format::_Align_right, + __nfill, _CharT('0')); + } +#endif + + return __format::__write_padded_as_spec(__str, __n, __fc, _M_spec, + __format::_Align_right); + } + + private: + __format::_Spec<_CharT> _M_spec{}; + }; + } // namespace __format /// @endcond @@ -2845,120 +2979,15 @@ namespace __format constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) - { - __format::_Spec<_CharT> __spec{}; - const auto __last = __pc.end(); - auto __first = __pc.begin(); - - auto __finalize = [this, &__spec] { - _M_spec = __spec; - }; - - auto __finished = [&] { - if (__first == __last || *__first == '}') - { - __finalize(); - return true; - } - return false; - }; - - if (__finished()) - return __first; - - __first = __spec._M_parse_fill_and_align(__first, __last); - if (__finished()) - return __first; - -// _GLIBCXX_RESOLVE_LIB_DEFECTS -// P2510R3 Formatting pointers -#if __glibcxx_format >= 202304L - __first = __spec._M_parse_zero_fill(__first, __last); - if (__finished()) - return __first; -#endif - - __first = __spec._M_parse_width(__first, __last, __pc); - - if (__first != __last) - { - if (*__first == 'p') - ++__first; -#if __glibcxx_format >= 202304L - else if (*__first == 'P') - { - __spec._M_type = __format::_Pres_P; - ++__first; - } -#endif - } - - if (__finished()) - return __first; - - __format::__failed_to_parse_format_spec(); - } + { return _M_f.parse(__pc); } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(const void* __v, basic_format_context<_Out, _CharT>& __fc) const - { - auto __u = reinterpret_cast<__UINTPTR_TYPE__>(__v); - char __buf[2 + sizeof(__v) * 2]; - auto [__ptr, __ec] = std::to_chars(__buf + 2, std::end(__buf), - __u, 16); - int __n = __ptr - __buf; - __buf[0] = '0'; - __buf[1] = 'x'; -#if __glibcxx_format >= 202304L - if (_M_spec._M_type == __format::_Pres_P) - { - __buf[1] = 'X'; - for (auto __p = __buf + 2; __p != __ptr; ++__p) -#if __has_builtin(__builtin_toupper) - *__p = __builtin_toupper(*__p); -#else - *__p = std::toupper(*__p); -#endif - } -#endif - - basic_string_view<_CharT> __str; - if constexpr (is_same_v<_CharT, char>) - __str = string_view(__buf, __n); -#ifdef _GLIBCXX_USE_WCHAR_T - else - { - auto __p = (_CharT*)__builtin_alloca(__n * sizeof(_CharT)); - std::__to_wstring_numeric(__buf, __n, __p); - __str = wstring_view(__p, __n); - } -#endif - -#if __glibcxx_format >= 202304L - if (_M_spec._M_zero_fill) - { - size_t __width = _M_spec._M_get_width(__fc); - if (__width <= __str.size()) - return __format::__write(__fc.out(), __str); - - auto __out = __fc.out(); - // Write "0x" or "0X" prefix before zero-filling. - __out = __format::__write(std::move(__out), __str.substr(0, 2)); - __str.remove_prefix(2); - size_t __nfill = __width - __n; - return __format::__write_padded(std::move(__out), __str, - __format::_Align_right, - __nfill, _CharT('0')); - } -#endif - - return __format::__write_padded_as_spec(__str, __n, __fc, _M_spec, - __format::_Align_right); - } + { return _M_f.format(__v, __fc); } private: - __format::_Spec<_CharT> _M_spec{}; + __format::__formatter_ptr<_CharT> _M_f; }; template<__format::__char _CharT> @@ -2977,7 +3006,7 @@ namespace __format { return _M_f.format(__v, __fc); } private: - formatter<const void*, _CharT> _M_f; + __format::__formatter_ptr<_CharT> _M_f; }; template<__format::__char _CharT> @@ -2996,7 +3025,7 @@ namespace __format { return _M_f.format(nullptr, __fc); } private: - formatter<const void*, _CharT> _M_f; + __format::__formatter_ptr<_CharT> _M_f; }; /// @} @@ -3024,59 +3053,6 @@ namespace __format : private formatter<__format::__disabled, wchar_t> { }; #endif -/// @cond undocumented -namespace __format -{ - template<typename _Tp, typename _Context, - typename _Formatter - = typename _Context::template formatter_type<remove_const_t<_Tp>>, - typename _ParseContext - = basic_format_parse_context<typename _Context::char_type>> - concept __parsable_with - = semiregular<_Formatter> - && requires (_Formatter __f, _ParseContext __pc) - { - { __f.parse(__pc) } -> same_as<typename _ParseContext::iterator>; - }; - - template<typename _Tp, typename _Context, - typename _Formatter - = typename _Context::template formatter_type<remove_const_t<_Tp>>, - typename _ParseContext - = basic_format_parse_context<typename _Context::char_type>> - concept __formattable_with - = semiregular<_Formatter> - && requires (const _Formatter __cf, _Tp&& __t, _Context __fc) - { - { __cf.format(__t, __fc) } -> same_as<typename _Context::iterator>; - }; - - // An unspecified output iterator type used in the `formattable` concept. - template<typename _CharT> - using _Iter_for = back_insert_iterator<basic_string<_CharT>>; - - template<typename _Tp, typename _CharT, - typename _Context = basic_format_context<_Iter_for<_CharT>, _CharT>> - concept __formattable_impl - = __parsable_with<_Tp, _Context> && __formattable_with<_Tp, _Context>; - - template<typename _Formatter> - concept __has_debug_format = requires(_Formatter __f) - { - __f.set_debug_format(); - }; - -} // namespace __format -/// @endcond - -#if __glibcxx_format_ranges // C++ >= 23 && HOSTED - // [format.formattable], concept formattable - template<typename _Tp, typename _CharT> - concept formattable - = __format::__formattable_impl<remove_reference_t<_Tp>, _CharT>; - -#endif // format_ranges - /// An iterator after the last character written, and the number of /// characters that would have been written. template<typename _Out> @@ -5250,26 +5226,13 @@ namespace __format return __format::__write_padded_as_spec(__str, __width, __fc, __spec); } - template<typename _Rg, typename _CharT> - concept __const_formattable_range - = ranges::input_range<const _Rg> - && formattable<ranges::range_reference_t<const _Rg>, _CharT>; - // _Rg& and const _Rg& are both formattable and use same formatter // specialization for their references. template<typename _Rg, typename _CharT> concept __simply_formattable_range = __const_formattable_range<_Rg, _CharT> && same_as<remove_cvref_t<ranges::range_reference_t<_Rg>>, - remove_cvref_t<ranges::range_reference_t<const _Rg>>>; - - template<typename _Rg, typename _CharT> - using __maybe_const_range - = __conditional_t<__const_formattable_range<_Rg, _CharT>, const _Rg, _Rg>; - - template<typename _Tp, typename _CharT> - using __maybe_const - = __conditional_t<formattable<const _Tp, _CharT>, const _Tp, _Tp>; + remove_cvref_t<ranges::range_reference_t<const _Rg>>>; template<size_t _Pos, typename _Tp, typename _CharT> struct __indexed_formatter_storage @@ -5493,7 +5456,7 @@ namespace __format }; // [format.range.formatter], class template range_formatter - template<typename _Tp, __format::__char _CharT = char> + template<typename _Tp, __format::__char _CharT> requires same_as<remove_cvref_t<_Tp>, _Tp> && formattable<_Tp, _CharT> class range_formatter { diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future index b7ab233..0806900 100644 --- a/libstdc++-v3/include/std/future +++ b/libstdc++-v3/include/std/future @@ -1486,12 +1486,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __future_base::_Task_state<_Fn, _Alloc, _Res(_Args...)> final : __future_base::_Task_state_base<_Res(_Args...)> { +#ifdef __cpp_lib_is_invocable // C++ >= 17 + static_assert(is_invocable_r_v<_Res, _Fn&, _Args...>); +#else + static_assert(__is_invocable<_Fn&, _Args...>::value, + "_Fn& is invocable with _Args..."); +#endif + template<typename _Fn2> _Task_state(_Fn2&& __fn, const _Alloc& __a) : _Task_state_base<_Res(_Args...)>(__a), _M_impl(std::forward<_Fn2>(__fn), __a) { } + template<typename _Fn2> + static shared_ptr<_Task_state_base<_Res(_Args...)>> + _S_create(_Fn2&& __fn, const _Alloc& __a) + { + return std::allocate_shared<_Task_state>(__a, + std::forward<_Fn2>(__fn), + __a); + } + private: virtual void _M_run(_Args&&... __args) @@ -1515,7 +1531,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } virtual shared_ptr<_Task_state_base<_Res(_Args...)>> - _M_reset(); + _M_reset() + { return _S_create(std::move(_M_impl._M_fn), _M_impl); } struct _Impl : _Alloc { @@ -1525,38 +1542,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Fn _M_fn; } _M_impl; }; - - template<typename _Signature, typename _Fn, - typename _Alloc = std::allocator<int>> - shared_ptr<__future_base::_Task_state_base<_Signature>> - __create_task_state(_Fn&& __fn, const _Alloc& __a = _Alloc()) - { - typedef typename decay<_Fn>::type _Fn2; - typedef __future_base::_Task_state<_Fn2, _Alloc, _Signature> _State; - return std::allocate_shared<_State>(__a, std::forward<_Fn>(__fn), __a); - } - - template<typename _Fn, typename _Alloc, typename _Res, typename... _Args> - shared_ptr<__future_base::_Task_state_base<_Res(_Args...)>> - __future_base::_Task_state<_Fn, _Alloc, _Res(_Args...)>::_M_reset() - { - return __create_task_state<_Res(_Args...)>(std::move(_M_impl._M_fn), - static_cast<_Alloc&>(_M_impl)); - } /// @endcond /// packaged_task template<typename _Res, typename... _ArgTypes> class packaged_task<_Res(_ArgTypes...)> { - typedef __future_base::_Task_state_base<_Res(_ArgTypes...)> _State_type; + using _State_type = __future_base::_Task_state_base<_Res(_ArgTypes...)>; shared_ptr<_State_type> _M_state; // _GLIBCXX_RESOLVE_LIB_DEFECTS // 3039. Unnecessary decay in thread and packaged_task template<typename _Fn, typename _Fn2 = __remove_cvref_t<_Fn>> - using __not_same - = typename enable_if<!is_same<packaged_task, _Fn2>::value>::type; + using __not_same = __enable_if_t<!is_same<packaged_task, _Fn2>::value>; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 4154. The Mandates for std::packaged_task's constructor + // from a callable entity should consider decaying. + template<typename _Fn, typename _Alloc = std::allocator<int>> + using _Task_state + = __future_base::_Task_state<__decay_t<_Fn>, _Alloc, + _Res(_ArgTypes...)>; public: // Construction and destruction @@ -1565,16 +1571,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Fn, typename = __not_same<_Fn>> explicit packaged_task(_Fn&& __fn) - : _M_state( - __create_task_state<_Res(_ArgTypes...)>(std::forward<_Fn>(__fn))) - { -#ifdef __cpp_lib_is_invocable // C++ >= 17 - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 4154. The Mandates for std::packaged_task's constructor - // from a callable entity should consider decaying - static_assert(is_invocable_r_v<_Res, decay_t<_Fn>&, _ArgTypes...>); -#endif - } + : _M_state(_Task_state<_Fn>::_S_create(std::forward<_Fn>(__fn), {})) + { } #if __cplusplus < 201703L // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -1583,8 +1581,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // 2921. packaged_task and type-erased allocators template<typename _Fn, typename _Alloc, typename = __not_same<_Fn>> packaged_task(allocator_arg_t, const _Alloc& __a, _Fn&& __fn) - : _M_state(__create_task_state<_Res(_ArgTypes...)>( - std::forward<_Fn>(__fn), __a)) + : _M_state(_Task_state<_Fn, _Alloc>::_S_create(std::forward<_Fn>(__fn), + __a)) { } // _GLIBCXX_RESOLVE_LIB_DEFECTS diff --git a/libstdc++-v3/include/std/queue b/libstdc++-v3/include/std/queue index 74b6c07..9052589 100644 --- a/libstdc++-v3/include/std/queue +++ b/libstdc++-v3/include/std/queue @@ -61,14 +61,88 @@ #include <bits/requires_hosted.h> // containers +#define __glibcxx_want_adaptor_iterator_pair_constructor +#define __glibcxx_want_containers_ranges +#include <bits/version.h> + #include <deque> #include <vector> #include <bits/stl_heap.h> #include <bits/stl_function.h> #include <bits/stl_queue.h> -#define __glibcxx_want_adaptor_iterator_pair_constructor -#define __glibcxx_want_containers_ranges -#include <bits/version.h> +#ifdef __glibcxx_format_ranges // C++ >= 23 && HOSTED +#include <bits/formatfwd.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + // Standard does not constrain accepted _CharT, we do so we can + // befriend specializations. + template<__format::__char _CharT, typename _Tp, + formattable<_CharT> _Container> + struct formatter<queue<_Tp, _Container>, _CharT> + { + private: + using __maybe_const_adaptor + = __conditional_t< + __format::__const_formattable_range<_Container, _CharT>, + const queue<_Tp, _Container>, queue<_Tp, _Container>>; + + public: + // Standard declares this as template accepting unconstrained + // ParseContext type. + constexpr typename basic_format_parse_context<_CharT>::iterator + parse(basic_format_parse_context<_CharT>& __pc) + { return _M_f.parse(__pc); } + + // Standard declares this as template accepting unconstrained + // FormatContext type. + template<typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + format(__maybe_const_adaptor& __a, + basic_format_context<_Out, _CharT>& __fc) const + { return _M_f.format(__a.c, __fc); } + + private: + // Standard uses formatter<ref_view<_Container>, _CharT>. + range_formatter<_Tp, _CharT> _M_f; + }; + + template<__format::__char _CharT, typename _Tp, + formattable<_CharT> _Container, typename _Compare> + struct formatter<priority_queue<_Tp, _Container, _Compare>, _CharT> + { + private: + using __maybe_const_adaptor + = __conditional_t< + __format::__const_formattable_range<_Container, _CharT>, + const priority_queue<_Tp, _Container, _Compare>, + priority_queue<_Tp, _Container, _Compare>>; + + public: + // Standard declares this as template accepting unconstrained + // ParseContext type. + constexpr typename basic_format_parse_context<_CharT>::iterator + parse(basic_format_parse_context<_CharT>& __pc) + { return _M_f.parse(__pc); } + + // Standard declares this as template accepting unconstrained + // FormatContext type. + template<typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + format(__maybe_const_adaptor& __a, + basic_format_context<_Out, _CharT>& __fc) const + { return _M_f.format(__a.c, __fc); } + + private: + // Standard uses formatter<ref_view<_Container>, _CharT>. + range_formatter<_Tp, _CharT> _M_f; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // __glibcxx_format_ranges + #endif /* _GLIBCXX_QUEUE */ diff --git a/libstdc++-v3/include/std/stack b/libstdc++-v3/include/std/stack index 5cea476..a57a5a0 100644 --- a/libstdc++-v3/include/std/stack +++ b/libstdc++-v3/include/std/stack @@ -61,11 +61,53 @@ #include <bits/requires_hosted.h> // containers -#include <deque> -#include <bits/stl_stack.h> - #define __glibcxx_want_adaptor_iterator_pair_constructor #define __glibcxx_want_containers_ranges #include <bits/version.h> +#include <deque> +#include <bits/stl_stack.h> + +#ifdef __glibcxx_format_ranges // C++ >= 23 && HOSTED +#include <bits/formatfwd.h> + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + // Standard does not constrain accepted _CharT, we do so we can + // befriend specializations. + template<__format::__char _CharT, typename _Tp, + formattable<_CharT> _Container> + struct formatter<stack<_Tp, _Container>, _CharT> + { + private: + using __maybe_const_adaptor + = __conditional_t< + __format::__const_formattable_range<_Container, _CharT>, + const stack<_Tp, _Container>, stack<_Tp, _Container>>; + + public: + // Standard declares this as template accepting unconstrained + // ParseContext type. + constexpr typename basic_format_parse_context<_CharT>::iterator + parse(basic_format_parse_context<_CharT>& __pc) + { return _M_f.parse(__pc); } + + // Standard declares this as template accepting unconstrained + // FormatContext type. + template<typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + format(__maybe_const_adaptor& __a, + basic_format_context<_Out, _CharT>& __fc) const + { return _M_f.format(__a.c, __fc); } + + private: + // Standard uses formatter<ref_view<_Container>, _CharT>. + range_formatter<_Tp, _CharT> _M_f; + }; +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // __glibcxx_format_ranges + + #endif /* _GLIBCXX_STACK */ diff --git a/libstdc++-v3/include/std/thread b/libstdc++-v3/include/std/thread index d2f91ad..0de08c0 100644 --- a/libstdc++-v3/include/std/thread +++ b/libstdc++-v3/include/std/thread @@ -297,7 +297,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif // __cpp_lib_jthread #ifdef __cpp_lib_formatters // C++ >= 23 - template<typename _CharT> + // We deviate from the standard, that does not put requirements + // on _CharT here. + template<__format::__char _CharT> requires is_pointer_v<thread::native_handle_type> || is_integral_v<thread::native_handle_type> class formatter<thread::id, _CharT> @@ -307,6 +309,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION parse(basic_format_parse_context<_CharT>& __pc) { __format::_Spec<_CharT> __spec{}; + __spec._M_align = __format::_Align_right; const auto __last = __pc.end(); auto __first = __pc.begin(); @@ -334,36 +337,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__finished()) return __first; - __throw_format_error("format error: invalid format-spec for " - "std::thread::id"); + std::__throw_format_error("format error: invalid format-spec for " + "std::thread::id"); } template<typename _Out> typename basic_format_context<_Out, _CharT>::iterator format(thread::id __id, basic_format_context<_Out, _CharT>& __fc) const { - basic_string_view<_CharT> __sv; - if constexpr (is_same_v<_CharT, char>) - __sv = "{}thread::id of a non-executing thread"; - else - __sv = L"{}thread::id of a non-executing thread"; - basic_string<_CharT> __str; + if (__id == thread::id()) - __sv.remove_prefix(2); - else { - using _FmtStr = __format::_Runtime_format_string<_CharT>; - // Convert non-void pointers to const void* for formatted output. - using __output_type - = __conditional_t<is_pointer_v<thread::native_handle_type>, - const void*, - thread::native_handle_type>; - auto __o = static_cast<__output_type>(__id._M_thread); - __sv = __str = std::format(_FmtStr(__sv.substr(0, 2)), __o); + const _CharT* __msg; + if constexpr (is_same_v<_CharT, char>) + __msg = "thread::id of a non-executing thread"; + else + __msg = L"thread::id of a non-executing thread"; + + __format::__formatter_str<_CharT> __formatter(_M_spec); + return __formatter.format(__msg, __fc); } - return __format::__write_padded_as_spec(__sv, __sv.size(), - __fc, _M_spec, - __format::_Align_right); + + using _HandleFormatter + = __conditional_t<is_pointer_v<thread::native_handle_type>, + __format::__formatter_ptr<_CharT>, + __format::__formatter_int<_CharT>>; + + _HandleFormatter __formatter(_M_spec); + return __formatter.format(__id._M_thread, __fc); } private: |