diff options
Diffstat (limited to 'libstdc++-v3/include/std')
-rw-r--r-- | libstdc++-v3/include/std/deque | 1 | ||||
-rw-r--r-- | libstdc++-v3/include/std/format | 1255 | ||||
-rw-r--r-- | libstdc++-v3/include/std/forward_list | 1 | ||||
-rw-r--r-- | libstdc++-v3/include/std/list | 1 | ||||
-rw-r--r-- | libstdc++-v3/include/std/map | 1 | ||||
-rw-r--r-- | libstdc++-v3/include/std/numeric | 8 | ||||
-rw-r--r-- | libstdc++-v3/include/std/queue | 1 | ||||
-rw-r--r-- | libstdc++-v3/include/std/ranges | 1 | ||||
-rw-r--r-- | libstdc++-v3/include/std/set | 1 | ||||
-rw-r--r-- | libstdc++-v3/include/std/stack | 1 | ||||
-rw-r--r-- | libstdc++-v3/include/std/string | 1 | ||||
-rw-r--r-- | libstdc++-v3/include/std/unordered_map | 1 | ||||
-rw-r--r-- | libstdc++-v3/include/std/unordered_set | 1 | ||||
-rw-r--r-- | libstdc++-v3/include/std/vector | 1 |
14 files changed, 1146 insertions, 129 deletions
diff --git a/libstdc++-v3/include/std/deque b/libstdc++-v3/include/std/deque index 8fd7300..2badab8 100644 --- a/libstdc++-v3/include/std/deque +++ b/libstdc++-v3/include/std/deque @@ -72,6 +72,7 @@ #define __glibcxx_want_algorithm_default_value_type #define __glibcxx_want_allocator_traits_is_always_equal +#define __glibcxx_want_containers_ranges #define __glibcxx_want_erase_if #define __glibcxx_want_nonmember_container_access #include <bits/version.h> diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format index 2e9319c..e557e10 100644 --- a/libstdc++-v3/include/std/format +++ b/libstdc++-v3/include/std/format @@ -80,8 +80,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// @cond undocumented namespace __format { - // Type-erased character sink. + // STATICALLY-WIDEN, see C++20 [time.general] + // It doesn't matter for format strings (which can only be char or wchar_t) + // but this returns the narrow string for anything that isn't wchar_t. This + // is done because const char* can be inserted into any ostream type, and + // will be widened at runtime if necessary. + template<typename _CharT> + consteval auto + _Widen(const char* __narrow, const wchar_t* __wide) + { + if constexpr (is_same_v<_CharT, wchar_t>) + return __wide; + else + return __narrow; + } +#define _GLIBCXX_WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S) +#define _GLIBCXX_WIDEN(S) _GLIBCXX_WIDEN_(_CharT, S) + + // Size for stack located buffer + template<typename _CharT> + constexpr size_t __stackbuf_size = 32 * sizeof(void*) / sizeof(_CharT); + + // Type-erased character sinks. template<typename _CharT> class _Sink; + template<typename _CharT> class _Fixedbuf_sink; + template<typename _Seq> class _Seq_sink; + + template<typename _CharT, typename _Alloc = allocator<_CharT>> + using _Str_sink + = _Seq_sink<basic_string<_CharT, char_traits<_CharT>, _Alloc>>; + + // template<typename _CharT, typename _Alloc = allocator<_CharT>> + // using _Vec_sink = _Seq_sink<vector<_CharT, _Alloc>>; + // Output iterator that writes to a type-erase character sink. template<typename _CharT> class _Sink_iter; @@ -448,9 +479,10 @@ namespace __format _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 and bool. - _Pres_esc = 0xf, // For strings and charT. + _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 }; enum _Align { @@ -517,42 +549,48 @@ namespace __format // pre: __first != __last constexpr iterator _M_parse_fill_and_align(iterator __first, iterator __last) noexcept + { return _M_parse_fill_and_align(__first, __last, "{"); } + + // pre: __first != __last + constexpr iterator + _M_parse_fill_and_align(iterator __first, iterator __last, string_view __not_fill) noexcept { - if (*__first != '{') + for (char __c : __not_fill) + if (*__first == static_cast<_CharT>(__c)) + return __first; + + using namespace __unicode; + if constexpr (__literal_encoding_is_unicode<_CharT>()) { - using namespace __unicode; - if constexpr (__literal_encoding_is_unicode<_CharT>()) - { - // Accept any UCS scalar value as fill character. - _Utf32_view<ranges::subrange<iterator>> __uv({__first, __last}); - if (!__uv.empty()) - { - auto __beg = __uv.begin(); - char32_t __c = *__beg++; - if (__is_scalar_value(__c)) - if (auto __next = __beg.base(); __next != __last) - if (_Align __align = _S_align(*__next)) - { - _M_fill = __c; - _M_align = __align; - return ++__next; - } - } - } - else if (__last - __first >= 2) - if (_Align __align = _S_align(__first[1])) - { - _M_fill = *__first; - _M_align = __align; - return __first + 2; - } + // Accept any UCS scalar value as fill character. + _Utf32_view<ranges::subrange<iterator>> __uv({__first, __last}); + if (!__uv.empty()) + { + auto __beg = __uv.begin(); + char32_t __c = *__beg++; + if (__is_scalar_value(__c)) + if (auto __next = __beg.base(); __next != __last) + if (_Align __align = _S_align(*__next)) + { + _M_fill = __c; + _M_align = __align; + return ++__next; + } + } + } + else if (__last - __first >= 2) + if (_Align __align = _S_align(__first[1])) + { + _M_fill = *__first; + _M_align = __align; + return __first + 2; + } - if (_Align __align = _S_align(__first[0])) - { - _M_fill = ' '; - _M_align = __align; - return __first + 1; - } + if (_Align __align = _S_align(__first[0])) + { + _M_fill = ' '; + _M_align = __align; + return __first + 1; } return __first; } @@ -848,6 +886,302 @@ namespace __format __spec._M_fill); } + // Values are indices into _Escapes::all. + enum class _Term_char : unsigned char { + _Tc_quote = 12, + _Tc_apos = 15 + }; + + template<typename _CharT> + struct _Escapes + { + using _Str_view = basic_string_view<_CharT>; + + static consteval + _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); } + + static consteval + _Str_view _S_newline() + { return _S_all().substr(3, 3); } + + static consteval + _Str_view _S_return() + { return _S_all().substr(6, 3); } + + static consteval + _Str_view _S_bslash() + { return _S_all().substr(9, 3); } + + static consteval + _Str_view _S_quote() + { return _S_all().substr(12, 3); } + + static consteval + _Str_view _S_apos() + { return _S_all().substr(15, 3); } + + static consteval + _Str_view _S_u() + { return _S_all().substr(18, 2); } + + static consteval + _Str_view _S_x() + { return _S_all().substr(20, 2); } + }; + + template<typename _CharT> + struct _Separators + { + using _Str_view = basic_string_view<_CharT>; + + static consteval + _Str_view _S_all() + { return _GLIBCXX_WIDEN("[]{}(), : "); } + + static consteval + _Str_view _S_squares() + { return _S_all().substr(0, 2); } + + static consteval + _Str_view _S_braces() + { return _S_all().substr(2, 2); } + + static consteval + _Str_view _S_parens() + { return _S_all().substr(4, 2); } + + static consteval + _Str_view _S_comma() + { return _S_all().substr(6, 2); } + + static consteval + _Str_view _S_colon() + { return _S_all().substr(8, 2); } + }; + + template<typename _CharT> + constexpr bool __should_escape_ascii(_CharT __c, _Term_char __term) + { + using _Esc = _Escapes<_CharT>; + switch (__c) + { + case _Esc::_S_tab()[0]: + case _Esc::_S_newline()[0]: + case _Esc::_S_return()[0]: + case _Esc::_S_bslash()[0]: + return true; + case _Esc::_S_quote()[0]: + return __term == _Term_char::_Tc_quote; + case _Esc::_S_apos()[0]: + return __term == _Term_char::_Tc_apos; + default: + return (__c >= 0 && __c < 0x20) || __c == 0x7f; + }; + } + + // @pre __c <= 0x10FFFF + constexpr bool __should_escape_unicode(char32_t __c, bool __prev_esc) + { + if (__unicode::__should_escape_category(__c)) + return __c != U' '; + if (!__prev_esc) + return false; + return __unicode::__grapheme_cluster_break_property(__c) + == __unicode::_Gcb_property::_Gcb_Extend; + } + + using uint_least32_t = __UINT_LEAST32_TYPE__; + template<typename _Out, typename _CharT> + _Out + __write_escape_seq(_Out __out, uint_least32_t __val, + basic_string_view<_CharT> __prefix) + { + using _Str_view = basic_string_view<_CharT>; + constexpr size_t __max = 8; + char __buf[__max]; + const string_view __narrow( + __buf, + std::__to_chars_i<uint_least32_t>(__buf, __buf + __max, __val, 16).ptr); + + __out = __format::__write(__out, __prefix); + *__out = _Separators<_CharT>::_S_braces()[0]; + ++__out; + if constexpr (is_same_v<char, _CharT>) + __out = __format::__write(__out, __narrow); +#ifdef _GLIBCXX_USE_WCHAR_T + else + { + _CharT __wbuf[__max]; + const size_t __n = __narrow.size(); + std::__to_wstring_numeric(__narrow.data(), __n, __wbuf); + __out = __format::__write(__out, _Str_view(__wbuf, __n)); + } +#endif + *__out = _Separators<_CharT>::_S_braces()[1]; + return ++__out; + } + + template<typename _Out, typename _CharT> + _Out + __write_escaped_char(_Out __out, _CharT __c) + { + using _UChar = make_unsigned_t<_CharT>; + using _Esc = _Escapes<_CharT>; + switch (__c) + { + case _Esc::_S_tab()[0]: + return __format::__write(__out, _Esc::_S_tab().substr(1, 2)); + case _Esc::_S_newline()[0]: + return __format::__write(__out, _Esc::_S_newline().substr(1, 2)); + case _Esc::_S_return()[0]: + return __format::__write(__out, _Esc::_S_return().substr(1, 2)); + case _Esc::_S_bslash()[0]: + return __format::__write(__out, _Esc::_S_bslash().substr(1, 2)); + case _Esc::_S_quote()[0]: + return __format::__write(__out, _Esc::_S_quote().substr(1, 2)); + 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()); + } + } + + template<typename _CharT, typename _Out> + _Out + __write_escaped_ascii(_Out __out, + basic_string_view<_CharT> __str, + _Term_char __term) + { + using _Str_view = basic_string_view<_CharT>; + auto __first = __str.begin(); + auto const __last = __str.end(); + while (__first != __last) + { + auto __print = __first; + // assume anything outside ASCII is printable + while (__print != __last + && !__format::__should_escape_ascii(*__print, __term)) + ++__print; + + if (__print != __first) + __out = __format::__write(__out, _Str_view(__first, __print)); + + if (__print == __last) + return __out; + + __first = __print; + __out = __format::__write_escaped_char(__out, *__first); + ++__first; + } + return __out; + } + + template<typename _CharT, typename _Out> + _Out + __write_escaped_unicode(_Out __out, + basic_string_view<_CharT> __str, + _Term_char __term) + { + using _Str_view = basic_string_view<_CharT>; + using _UChar = make_unsigned_t<_CharT>; + using _Esc = _Escapes<_CharT>; + + static constexpr char32_t __replace = U'\uFFFD'; + static constexpr _Str_view __replace_rep = [] + { + // N.B. "\uFFFD" is ill-formed if encoding is not unicode. + if constexpr (is_same_v<char, _CharT>) + return "\xEF\xBF\xBD"; + else + return L"\xFFFD"; + }(); + + __unicode::_Utf_view<char32_t, _Str_view> __v(std::move(__str)); + auto __first = __v.begin(); + auto const __last = __v.end(); + + bool __prev_esc = true; + while (__first != __last) + { + bool __esc_ascii = false; + bool __esc_unicode = false; + bool __esc_replace = false; + auto __should_escape = [&](auto const& __it) + { + if (*__it <= 0x7f) + return __esc_ascii + = __format::__should_escape_ascii(*__it.base(), __term); + if (__format::__should_escape_unicode(*__it, __prev_esc)) + return __esc_unicode = true; + if (*__it == __replace) + { + _Str_view __units(__it.base(), __it._M_units()); + return __esc_replace = (__units != __replace_rep); + } + return false; + }; + + auto __print = __first; + while (__print != __last && !__should_escape(__print)) + { + __prev_esc = false; + ++__print; + } + + if (__print != __first) + __out = __format::__write(__out, _Str_view(__first.base(), __print.base())); + + if (__print == __last) + return __out; + + __first = __print; + if (__esc_ascii) + __out = __format::__write_escaped_char(__out, *__first.base()); + else if (__esc_unicode) + __out = __format::__write_escape_seq(__out, *__first, _Esc::_S_u()); + else // __esc_replace + for (_CharT __c : _Str_view(__first.base(), __first._M_units())) + __out = __format::__write_escape_seq(__out, + static_cast<_UChar>(__c), + _Esc::_S_x()); + __prev_esc = true; + ++__first; + + } + return __out; + } + + template<typename _CharT, typename _Out> + _Out + __write_escaped(_Out __out, basic_string_view<_CharT> __str, _Term_char __term) + { + *__out = _Escapes<_CharT>::_S_term(__term); + ++__out; + + if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>()) + __out = __format::__write_escaped_unicode(__out, __str, __term); + else if constexpr (is_same_v<char, _CharT> + && __unicode::__literal_encoding_is_extended_ascii()) + __out = __format::__write_escaped_ascii(__out, __str, __term); + else + // TODO Handle non-ascii extended encoding + __out = __format::__write_escaped_ascii(__out, __str, __term); + + *__out = _Escapes<_CharT>::_S_term(__term); + return ++__out; + } + // A lightweight optional<locale>. struct _Optional_locale { @@ -924,6 +1258,13 @@ namespace __format template<__char _CharT> struct __formatter_str { + __formatter_str() = default; + + constexpr + __formatter_str(_Spec<_CharT> __spec) noexcept + : _M_spec(__spec) + { } + constexpr typename basic_format_parse_context<_CharT>::iterator parse(basic_format_parse_context<_CharT>& __pc) { @@ -961,7 +1302,7 @@ namespace __format if (*__first == 's') ++__first; -#if __cpp_lib_format_ranges +#if __glibcxx_format_ranges // C++ >= 23 && HOSTED else if (*__first == '?') { __spec._M_type = _Pres_esc; @@ -980,43 +1321,107 @@ namespace __format format(basic_string_view<_CharT> __s, basic_format_context<_Out, _CharT>& __fc) const { - if (_M_spec._M_type == _Pres_esc) + constexpr auto __term = __format::_Term_char::_Tc_quote; + const auto __write_direct = [&] { - // TODO: C++23 escaped string presentation - } + if (_M_spec._M_type == _Pres_esc) + return __format::__write_escaped(__fc.out(), __s, __term); + else + return __format::__write(__fc.out(), __s); + }; if (_M_spec._M_width_kind == _WP_none && _M_spec._M_prec_kind == _WP_none) - return __format::__write(__fc.out(), __s); + return __write_direct(); - size_t __estimated_width; - if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>()) + const size_t __prec = + _M_spec._M_prec_kind != _WP_none + ? _M_spec._M_get_precision(__fc) + : basic_string_view<_CharT>::npos; + + const size_t __estimated_width = _S_trunc(__s, __prec); + // N.B. Escaping only increases width + if (_M_spec._M_get_width(__fc) <= __estimated_width + && _M_spec._M_prec_kind == _WP_none) + return __write_direct(); + + if (_M_spec._M_type != _Pres_esc) + return __format::__write_padded_as_spec(__s, __estimated_width, + __fc, _M_spec); + + __format::_Str_sink<_CharT> __sink; + __format::__write_escaped(__sink.out(), __s, __term); + basic_string_view<_CharT> __escaped(__sink.view().data(), + __sink.view().size()); + const size_t __escaped_width = _S_trunc(__escaped, __prec); + // 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. + return __format::__write_padded_as_spec(__escaped, __escaped_width, + __fc, _M_spec); + } + +#if __glibcxx_format_ranges // C++ >= 23 && HOSTED + template<ranges::input_range _Rg, typename _Out> + requires same_as<remove_cvref_t<ranges::range_reference_t<_Rg>>, _CharT> + typename basic_format_context<_Out, _CharT>::iterator + _M_format_range(_Rg&& __rg, basic_format_context<_Out, _CharT>& __fc) const + { + using _String = basic_string<_CharT>; + using _String_view = basic_string_view<_CharT>; + if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>) { - if (_M_spec._M_prec_kind != _WP_none) + const size_t __n(ranges::distance(__rg)); + if constexpr (ranges::contiguous_range<_Rg>) + return format(_String_view(ranges::data(__rg), __n), __fc); + else if (__n <= __format::__stackbuf_size<_CharT>) { - size_t __prec = _M_spec._M_get_precision(__fc); - __estimated_width = __unicode::__truncate(__s, __prec); + _CharT __buf[__format::__stackbuf_size<_CharT>]; + ranges::copy(__rg, __buf); + return format(_String_view(__buf, __n), __fc); + } + else if constexpr (ranges::sized_range<_Rg>) + return format(_String(from_range, __rg), __fc); + else if constexpr (ranges::random_access_range<_Rg>) + { + ranges::iterator_t<_Rg> __first = ranges::begin(__rg); + ranges::subrange __sub(__first, __first + __n); + return format(_String(from_range, __sub), __fc); } else - __estimated_width = __unicode::__field_width(__s); + { + // N.B. preserve the computed size + ranges::subrange __sub(__rg, __n); + return format(_String(from_range, __sub), __fc); + } } else - { - __s = __s.substr(0, _M_spec._M_get_precision(__fc)); - __estimated_width = __s.size(); - } - - return __format::__write_padded_as_spec(__s, __estimated_width, - __fc, _M_spec); + return format(_String(from_range, __rg), __fc); } -#if __cpp_lib_format_ranges constexpr void set_debug_format() noexcept { _M_spec._M_type = _Pres_esc; } #endif private: + static size_t + _S_trunc(basic_string_view<_CharT>& __s, size_t __prec) + { + if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>()) + { + if (__prec != basic_string_view<_CharT>::npos) + return __unicode::__truncate(__s, __prec); + else + return __unicode::__field_width(__s); + } + else + { + __s = __s.substr(0, __prec); + return __s.size(); + } + } + _Spec<_CharT> _M_spec{}; }; @@ -1120,7 +1525,7 @@ namespace __format ++__first; } break; -#if __cpp_lib_format_ranges +#if __glibcxx_format_ranges // C++ >= 23 && HOSTED case '?': if (__type == _AsChar) { @@ -1272,7 +1677,7 @@ namespace __format _S_character_width(_CharT __c) { // N.B. single byte cannot encode charcter of width greater than 1 - if constexpr (sizeof(_CharT) > 1u && + if constexpr (sizeof(_CharT) > 1u && __unicode::__literal_encoding_is_unicode<_CharT>()) return __unicode::__field_width(__c); else @@ -1286,7 +1691,33 @@ namespace __format { return __format::__write_padded_as_spec({&__c, 1u}, _S_character_width(__c), - __fc, _M_spec); + __fc, _M_spec); + } + + 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); + + _CharT __buf[12]; + __format::_Fixedbuf_sink<_CharT> __sink(__buf); + __format::__write_escaped(__sink.out(), __in, __term); + + 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, + __fc, _M_spec); } template<typename _Int> @@ -1973,15 +2404,12 @@ namespace __format || _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) - { - // TODO - return __fc.out(); - } + return _M_f._M_format_character_escaped(__u, __fc); else return _M_f.format(static_cast<make_unsigned_t<_CharT>>(__u), __fc); } -#if __cpp_lib_format_ranges +#if __glibcxx_format_ranges // C++ >= 23 && HOSTED constexpr void set_debug_format() noexcept { _M_f._M_spec._M_type = __format::_Pres_esc; } @@ -2012,15 +2440,12 @@ namespace __format || _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) - { - // TODO - return __fc.out(); - } + return _M_f._M_format_character_escaped(__u, __fc); else return _M_f.format(static_cast<unsigned char>(__u), __fc); } -#if __cpp_lib_format_ranges +#if __glibcxx_format_ranges // C++ >= 23 && HOSTED constexpr void set_debug_format() noexcept { _M_f._M_spec._M_type = __format::_Pres_esc; } @@ -2050,7 +2475,7 @@ namespace __format format(_CharT* __u, basic_format_context<_Out, _CharT>& __fc) const { return _M_f.format(__u, __fc); } -#if __cpp_lib_format_ranges +#if __glibcxx_format_ranges // C++ >= 23 && HOSTED constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); } #endif @@ -2075,7 +2500,7 @@ namespace __format basic_format_context<_Out, _CharT>& __fc) const { return _M_f.format(__u, __fc); } -#if __cpp_lib_format_ranges +#if __glibcxx_format_ranges // C++ >= 23 && HOSTED constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); } #endif @@ -2099,7 +2524,7 @@ namespace __format basic_format_context<_Out, _CharT>& __fc) const { return _M_f.format({__u, _Nm}, __fc); } -#if __cpp_lib_format_ranges +#if __glibcxx_format_ranges // C++ >= 23 && HOSTED constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); } #endif @@ -2123,7 +2548,7 @@ namespace __format basic_format_context<_Out, char>& __fc) const { return _M_f.format(__u, __fc); } -#if __cpp_lib_format_ranges +#if __glibcxx_format_ranges // C++ >= 23 && HOSTED constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); } #endif @@ -2148,7 +2573,7 @@ namespace __format basic_format_context<_Out, wchar_t>& __fc) const { return _M_f.format(__u, __fc); } -#if __cpp_lib_format_ranges +#if __glibcxx_format_ranges // C++ >= 23 && HOSTED constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); } #endif @@ -2173,7 +2598,7 @@ namespace __format basic_format_context<_Out, char>& __fc) const { return _M_f.format(__u, __fc); } -#if __cpp_lib_format_ranges +#if __glibcxx_format_ranges // C++ >= 23 && HOSTED constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); } #endif @@ -2198,7 +2623,7 @@ namespace __format basic_format_context<_Out, wchar_t>& __fc) const { return _M_f.format(__u, __fc); } -#if __cpp_lib_format_ranges +#if __glibcxx_format_ranges // C++ >= 23 && HOSTED constexpr void set_debug_format() noexcept { _M_f.set_debug_format(); } #endif @@ -2575,7 +3000,7 @@ namespace __format }; /// @} -#if defined _GLIBCXX_USE_WCHAR_T && __cpp_lib_format_ranges +#if defined _GLIBCXX_USE_WCHAR_T && __glibcxx_format_ranges // _GLIBCXX_RESOLVE_LIB_DEFECTS // 3944. Formatters converting sequences of char to sequences of wchar_t @@ -2635,32 +3060,21 @@ namespace __format 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 -// Concept std::formattable was introduced by P2286R8 "Formatting Ranges", -// but we can't guard it with __cpp_lib_format_ranges until we define that! -#if __cplusplus > 202002L +#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 -#if __cpp_lib_format_ranges - /// @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>; -} // namespace __format - /// @endcond #endif // format_ranges /// An iterator after the last character written, and the number of @@ -2859,12 +3273,38 @@ namespace __format { return _Sink_iter<_CharT>(*this); } }; + + template<typename _CharT> + class _Fixedbuf_sink final : public _Sink<_CharT> + { + void + _M_overflow() override + { + __glibcxx_assert(false); + this->_M_rewind(); + } + + public: + [[__gnu__::__always_inline__]] + constexpr explicit + _Fixedbuf_sink(span<_CharT> __buf) + : _Sink<_CharT>(__buf) + { } + + constexpr basic_string_view<_CharT> + view() const + { + auto __s = this->_M_used(); + return basic_string_view<_CharT>(__s.data(), __s.size()); + } + }; + // A sink with an internal buffer. This is used to implement concrete sinks. template<typename _CharT> class _Buf_sink : public _Sink<_CharT> { protected: - _CharT _M_buf[32 * sizeof(void*) / sizeof(_CharT)]; + _CharT _M_buf[__stackbuf_size<_CharT>]; [[__gnu__::__always_inline__]] constexpr @@ -2993,13 +3433,6 @@ namespace __format } }; - template<typename _CharT, typename _Alloc = allocator<_CharT>> - using _Str_sink - = _Seq_sink<basic_string<_CharT, char_traits<_CharT>, _Alloc>>; - - // template<typename _CharT, typename _Alloc = allocator<_CharT>> - // using _Vec_sink = _Seq_sink<vector<_CharT, _Alloc>>; - // A sink that writes to an output iterator. // Writes to a fixed-size buffer and then flushes to the output iterator // when the buffer fills up. @@ -3675,17 +4108,17 @@ namespace __format return _M_visit([&__vis]<typename _Tp>(_Tp& __val) -> decltype(auto) { constexpr bool __user_facing = __is_one_of<_Tp, - monostate, bool, _CharT, - int, unsigned int, long long int, unsigned long long int, - float, double, long double, - const _CharT*, basic_string_view<_CharT>, - const void*, handle>::value; + monostate, bool, _CharT, + int, unsigned int, long long int, unsigned long long int, + float, double, long double, + const _CharT*, basic_string_view<_CharT>, + const void*, handle>::value; if constexpr (__user_facing) return std::forward<_Visitor>(__vis)(__val); else { - handle __h(__val); - return std::forward<_Visitor>(__vis)(__h); + handle __h(__val); + return std::forward<_Visitor>(__vis)(__h); } }, __type); } @@ -4713,7 +5146,7 @@ namespace __format } #endif -#if __cpp_lib_format_ranges +#if __glibcxx_format_ranges // C++ >= 23 && HOSTED // [format.range], formatting of ranges // [format.range.fmtkind], variable template format_kind enum class range_format { @@ -4727,7 +5160,10 @@ namespace __format /// @cond undocumented template<typename _Rg> - constexpr auto format_kind = not defined(format_kind<_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 @@ -4758,29 +5194,602 @@ namespace __format template<ranges::input_range _Rg> requires same_as<_Rg, remove_cvref_t<_Rg>> constexpr range_format format_kind<_Rg> = __fmt_kind<_Rg>(); - // [format.range.formatter], class template range_formatter - template<typename _Tp, typename _CharT = char> - requires same_as<remove_cvref_t<_Tp>, _Tp> && formattable<_Tp, _CharT> - class range_formatter; // TODO - /// @cond undocumented namespace __format { - // [format.range.fmtdef], class template range-default-formatter - template<range_format _Kind, ranges::input_range _Rg, typename _CharT> - struct __range_default_formatter; // TODO + template<typename _CharT, typename _Out, typename _Callback> + typename basic_format_context<_Out, _CharT>::iterator + __format_padded(basic_format_context<_Out, _CharT>& __fc, + const _Spec<_CharT>& __spec, + _Callback&& __call) + { + // This is required to implement formatting with padding, + // as we need to format to temporary buffer, using the same iterator. + static_assert(is_same_v<_Out, __format::_Sink_iter<_CharT>>); + + if (__spec._M_get_width(__fc) == 0) + return __call(__fc); + + struct _Restore_out + { + _Restore_out(basic_format_context<_Sink_iter<_CharT>, _CharT>& __fc) + : _M_ctx(std::addressof(__fc)), _M_out(__fc.out()) + { } + + void _M_trigger() + { + if (_M_ctx) + _M_ctx->advance_to(_M_out); + _M_ctx = nullptr; + } + + ~_Restore_out() + { _M_trigger(); } + + private: + basic_format_context<_Sink_iter<_CharT>, _CharT>* _M_ctx; + _Sink_iter<_CharT> _M_out; + }; + + _Restore_out __restore(__fc); + // TODO Consider double sinking, first buffer of width + // size and then original sink, if first buffer is overun + // we do not need to align + _Str_sink<_CharT> __buf; + __fc.advance_to(__buf.out()); + __call(__fc); + __restore._M_trigger(); + + basic_string_view<_CharT> __str(__buf.view()); + size_t __width; + if constexpr (__unicode::__literal_encoding_is_unicode<_CharT>()) + __width = __unicode::__field_width(__str); + else + __width = __str.size(); + + 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>; + + template<size_t _Pos, typename _Tp, typename _CharT> + struct __indexed_formatter_storage + { + constexpr void + _M_parse() + { + basic_format_parse_context<_CharT> __pc({}); + if (_M_formatter.parse(__pc) != __pc.end()) + __format::__failed_to_parse_format_spec(); + } + + template<typename _Out> + void + _M_format(__maybe_const<_Tp, _CharT>& __elem, + basic_format_context<_Out, _CharT>& __fc, + basic_string_view<_CharT> __sep) const + { + if constexpr (_Pos != 0) + __fc.advance_to(__format::__write(__fc.out(), __sep)); + __fc.advance_to(_M_formatter.format(__elem, __fc)); + } + + [[__gnu__::__always_inline__]] + constexpr void + set_debug_format() + { + if constexpr (__has_debug_format<formatter<_Tp, _CharT>>) + _M_formatter.set_debug_format(); + } + + private: + formatter<_Tp, _CharT> _M_formatter; + }; + + template<typename _CharT, typename... _Tps> + class __tuple_formatter + { + using _String_view = basic_string_view<_CharT>; + using _Seps = __format::_Separators<_CharT>; + + public: + constexpr void + set_separator(basic_string_view<_CharT> __sep) noexcept + { _M_sep = __sep; } + + constexpr void + set_brackets(basic_string_view<_CharT> __open, + basic_string_view<_CharT> __close) noexcept + { + _M_open = __open; + _M_close = __close; + } + + // We deviate from standard, that declares this as template accepting + // unconstrained ParseContext type, which seems unimplementable. + constexpr typename basic_format_parse_context<_CharT>::iterator + parse(basic_format_parse_context<_CharT>& __pc) + { + auto __first = __pc.begin(); + const auto __last = __pc.end(); + __format::_Spec<_CharT> __spec{}; + + auto __finished = [&] + { + if (__first != __last && *__first != '}') + return false; + + _M_spec = __spec; + _M_felems._M_parse(); + _M_felems.set_debug_format(); + return true; + }; + + if (__finished()) + return __first; + + __first = __spec._M_parse_fill_and_align(__first, __last, "{:"); + if (__finished()) + return __first; + + __first = __spec._M_parse_width(__first, __last, __pc); + if (__finished()) + return __first; + + if (*__first == 'n') + { + ++__first; + _M_open = _M_close = _String_view(); + } + else if (*__first == 'm') + { + ++__first; + if constexpr (sizeof...(_Tps) == 2) + { + _M_sep = _Seps::_S_colon(); + _M_open = _M_close = _String_view(); + } + else + __throw_format_error("format error: 'm' specifier requires range" + " of pair or tuple of two elements"); + } + + if (__finished()) + return __first; + + __format::__failed_to_parse_format_spec(); + } + + protected: + template<typename _Tuple, typename _Out, size_t... _Ids> + typename basic_format_context<_Out, _CharT>::iterator + _M_format(_Tuple& __tuple, index_sequence<_Ids...>, + basic_format_context<_Out, _CharT>& __fc) const + { return _M_format_elems(std::get<_Ids>(__tuple)..., __fc); } + + template<typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + _M_format_elems(__maybe_const<_Tps, _CharT>&... __elems, + basic_format_context<_Out, _CharT>& __fc) const + { + return __format::__format_padded( + __fc, _M_spec, + [this, &__elems...](basic_format_context<_Out, _CharT>& __nfc) + { + __nfc.advance_to(__format::__write(__nfc.out(), _M_open)); + _M_felems._M_format(__elems..., __nfc, _M_sep); + return __format::__write(__nfc.out(), _M_close); + }); + } + + private: + template<size_t... _Ids> + struct __formatters_storage + : __indexed_formatter_storage<_Ids, _Tps, _CharT>... + { + template<size_t _Id, typename _Up> + using _Base = __indexed_formatter_storage<_Id, _Up, _CharT>; + + constexpr void + _M_parse() + { + (_Base<_Ids, _Tps>::_M_parse(), ...); + } + + template<typename _Out> + void + _M_format(__maybe_const<_Tps, _CharT>&... __elems, + basic_format_context<_Out, _CharT>& __fc, + _String_view __sep) const + { + (_Base<_Ids, _Tps>::_M_format(__elems, __fc, __sep), ...); + } + + constexpr void + set_debug_format() + { + (_Base<_Ids, _Tps>::set_debug_format(), ...); + } + }; + + template<size_t... _Ids> + static auto + _S_create_storage(index_sequence<_Ids...>) + -> __formatters_storage<_Ids...>; + using _Formatters + = decltype(_S_create_storage(index_sequence_for<_Tps...>())); + + _Spec<_CharT> _M_spec{}; + _String_view _M_open = _Seps::_S_parens().substr(0, 1); + _String_view _M_close = _Seps::_S_parens().substr(1, 1); + _String_view _M_sep = _Seps::_S_comma(); + _Formatters _M_felems; + }; + + template<typename _Tp> + concept __is_map_formattable + = __is_pair<_Tp> || (__is_tuple_v<_Tp> && tuple_size_v<_Tp> == 2); + } // namespace __format /// @endcond + // [format.tuple] Tuple formatter + template<__format::__char _CharT, formattable<_CharT> _Fp, + formattable<_CharT> _Sp> + struct formatter<pair<_Fp, _Sp>, _CharT> + : __format::__tuple_formatter<_CharT, remove_cvref_t<_Fp>, + remove_cvref_t<_Sp>> + { + private: + using __maybe_const_pair + = __conditional_t<formattable<const _Fp, _CharT> + && formattable<const _Sp, _CharT>, + const pair<_Fp, _Sp>, pair<_Fp, _Sp>>; + public: + // We deviate from standard, that declares this as template accepting + // unconstrained FormatContext type, which seems unimplementable. + template<typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + format(__maybe_const_pair& __p, + basic_format_context<_Out, _CharT>& __fc) const + { return this->_M_format_elems(__p.first, __p.second, __fc); } + }; + + template<__format::__char _CharT, formattable<_CharT>... _Tps> + struct formatter<tuple<_Tps...>, _CharT> + : __format::__tuple_formatter<_CharT, remove_cvref_t<_Tps>...> + { + private: + using __maybe_const_tuple + = __conditional_t<(formattable<const _Tps, _CharT> && ...), + const tuple<_Tps...>, tuple<_Tps...>>; + public: + // We deviate from standard, that declares this as template accepting + // unconstrained FormatContext type, which seems unimplementable. + template<typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + format(__maybe_const_tuple& __t, + basic_format_context<_Out, _CharT>& __fc) const + { return this->_M_format(__t, index_sequence_for<_Tps...>(), __fc); } + }; + + // [format.range.formatter], class template range_formatter + template<typename _Tp, __format::__char _CharT = char> + requires same_as<remove_cvref_t<_Tp>, _Tp> && formattable<_Tp, _CharT> + class range_formatter + { + using _String_view = basic_string_view<_CharT>; + using _Seps = __format::_Separators<_CharT>; + + public: + constexpr void + set_separator(basic_string_view<_CharT> __sep) noexcept + { _M_sep = __sep; } + + constexpr void + set_brackets(basic_string_view<_CharT> __open, + basic_string_view<_CharT> __close) noexcept + { + _M_open = __open; + _M_close = __close; + } + + constexpr formatter<_Tp, _CharT>& + underlying() noexcept + { return _M_fval; } + + constexpr const formatter<_Tp, _CharT>& + underlying() const noexcept + { return _M_fval; } + + // We deviate from standard, that declares this as template accepting + // unconstrained ParseContext type, which seems unimplementable. + constexpr typename basic_format_parse_context<_CharT>::iterator + parse(basic_format_parse_context<_CharT>& __pc) + { + auto __first = __pc.begin(); + const auto __last = __pc.end(); + __format::_Spec<_CharT> __spec{}; + bool __no_brace = false; + + auto __finished = [&] + { return __first == __last || *__first == '}'; }; + + auto __finalize = [&] + { + _M_spec = __spec; + return __first; + }; + + auto __parse_val = [&](_String_view __nfs = _String_view()) + { + basic_format_parse_context<_CharT> __npc(__nfs); + if (_M_fval.parse(__npc) != __npc.end()) + __format::__failed_to_parse_format_spec(); + if constexpr (__format::__has_debug_format<formatter<_Tp, _CharT>>) + _M_fval.set_debug_format(); + return __finalize(); + }; + + if (__finished()) + return __parse_val(); + + __first = __spec._M_parse_fill_and_align(__first, __last, "{:"); + if (__finished()) + return __parse_val(); + + __first = __spec._M_parse_width(__first, __last, __pc); + if (__finished()) + return __parse_val(); + + if (*__first == '?') + { + ++__first; + __spec._M_type = __format::_Pres_esc; + if (__finished() || *__first != 's') + __throw_format_error("format error: '?' is allowed only in" + " combination with 's'"); + } + + if (*__first == 's') + { + ++__first; + if constexpr (same_as<_Tp, _CharT>) + { + if (__spec._M_type != __format::_Pres_esc) + __spec._M_type = __format::_Pres_str; + if (__finished()) + return __finalize(); + __throw_format_error("format error: element format specifier" + " cannot be provided when 's' specifier is used"); + } + else + __throw_format_error("format error: 's' specifier requires" + " range of character types"); + } + + if (__finished()) + return __parse_val(); + + if (*__first == 'n') + { + ++__first; + _M_open = _M_close = _String_view(); + __no_brace = true; + } + + if (__finished()) + return __parse_val(); + + if (*__first == 'm') + { + _String_view __m(__first, 1); + ++__first; + if constexpr (__format::__is_map_formattable<_Tp>) + { + _M_sep = _Seps::_S_comma(); + if (!__no_brace) + { + _M_open = _Seps::_S_braces().substr(0, 1); + _M_close = _Seps::_S_braces().substr(1, 1); + } + if (__finished()) + return __parse_val(__m); + __throw_format_error("format error: element format specifier" + " cannot be provided when 'm' specifier is used"); + } + else + __throw_format_error("format error: 'm' specifier requires" + " range of pairs or tuples of two elements"); + } + + if (__finished()) + return __parse_val(); + + if (*__first == ':') + { + __pc.advance_to(++__first); + __first = _M_fval.parse(__pc); + } + + if (__finished()) + return __finalize(); + + __format::__failed_to_parse_format_spec(); + } + + // We deviate from standard, that declares this as template accepting + // unconstrained FormatContext type, which seems unimplementable. + template<ranges::input_range _Rg, typename _Out> + requires formattable<ranges::range_reference_t<_Rg>, _CharT> && + same_as<remove_cvref_t<ranges::range_reference_t<_Rg>>, _Tp> + typename basic_format_context<_Out, _CharT>::iterator + format(_Rg&& __rg, basic_format_context<_Out, _CharT>& __fc) const + { + using _Range = remove_reference_t<_Rg>; + if constexpr (__format::__simply_formattable_range<_Range, _CharT>) + return _M_format<const _Range>(__rg, __fc); + else + return _M_format(__rg, __fc); + } + + private: + template<ranges::input_range _Rg, typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + _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) + { + __format::__formatter_str __fstr(_M_spec); + return __fstr._M_format_range(__rg, __fc); + } + return __format::__format_padded( + __fc, _M_spec, + [this, &__rg](basic_format_context<_Out, _CharT>& __nfc) + { return _M_format_elems(__rg, __nfc); }); + } + + + template<ranges::input_range _Rg, typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + _M_format_elems(_Rg& __rg, + basic_format_context<_Out, _CharT>& __fc) const + { + auto __out = __format::__write(__fc.out(), _M_open); + + auto __first = ranges::begin(__rg); + auto const __last = ranges::end(__rg); + if (__first == __last) + return __format::__write(__out, _M_close); + + __fc.advance_to(__out); + __out = _M_fval.format(*__first, __fc); + for (++__first; __first != __last; ++__first) + { + __out = __format::__write(__out, _M_sep); + __fc.advance_to(__out); + __out = _M_fval.format(*__first, __fc); + } + + return __format::__write(__out, _M_close); + } + + __format::_Spec<_CharT> _M_spec{}; + _String_view _M_open = _Seps::_S_squares().substr(0, 1); + _String_view _M_close = _Seps::_S_squares().substr(1, 1); + _String_view _M_sep = _Seps::_S_comma(); + formatter<_Tp, _CharT> _M_fval; + }; + + // In standard this is shown as inheriting from specialization of + // exposition only specialization for range-default-formatter for + // each range_format. We opt for simpler implementation. // [format.range.fmtmap], [format.range.fmtset], [format.range.fmtstr], // specializations for maps, sets, and strings - template<ranges::input_range _Rg, typename _CharT> + template<ranges::input_range _Rg, __format::__char _CharT> requires (format_kind<_Rg> != range_format::disabled) && formattable<ranges::range_reference_t<_Rg>, _CharT> struct formatter<_Rg, _CharT> - : __format::__range_default_formatter<format_kind<_Rg>, _Rg, _CharT> - { }; + { + private: + static const bool _S_range_format_is_string = + (format_kind<_Rg> == range_format::string) + || (format_kind<_Rg> == range_format::debug_string); + using _Vt = remove_cvref_t< + ranges::range_reference_t< + __format::__maybe_const_range<_Rg, _CharT>>>; + + static consteval bool _S_is_correct() + { + if constexpr (_S_range_format_is_string) + static_assert(same_as<_Vt, _CharT>); + return true; + } + + static_assert(_S_is_correct()); + + public: + constexpr formatter() noexcept + { + using _Seps = __format::_Separators<_CharT>; + if constexpr (format_kind<_Rg> == range_format::map) + { + static_assert(__format::__is_map_formattable<_Vt>); + _M_under.set_brackets(_Seps::_S_braces().substr(0, 1), + _Seps::_S_braces().substr(1, 1)); + _M_under.underlying().set_brackets({}, {}); + _M_under.underlying().set_separator(_Seps::_S_colon()); + } + else if constexpr (format_kind<_Rg> == range_format::set) + _M_under.set_brackets(_Seps::_S_braces().substr(0, 1), + _Seps::_S_braces().substr(1, 1)); + } + + constexpr void + set_separator(basic_string_view<_CharT> __sep) noexcept + requires (!_S_range_format_is_string) + { _M_under.set_separator(__sep); } + + constexpr void + set_brackets(basic_string_view<_CharT> __open, + basic_string_view<_CharT> __close) noexcept + requires (!_S_range_format_is_string) + { _M_under.set_brackets(__open, __close); } + + // We deviate from standard, that declares this as template accepting + // unconstrained ParseContext type, which seems unimplementable. + constexpr typename basic_format_parse_context<_CharT>::iterator + parse(basic_format_parse_context<_CharT>& __pc) + { + auto __res = _M_under.parse(__pc); + if constexpr (format_kind<_Rg> == range_format::debug_string) + _M_under.set_debug_format(); + return __res; + } + + // We deviate from standard, that declares this as template accepting + // unconstrained FormatContext type, which seems unimplementable. + template<typename _Out> + typename basic_format_context<_Out, _CharT>::iterator + format(__format::__maybe_const_range<_Rg, _CharT>& __rg, + basic_format_context<_Out, _CharT>& __fc) const + { + if constexpr (_S_range_format_is_string) + return _M_under._M_format_range(__rg, __fc); + else + return _M_under.format(__rg, __fc); + } + + private: + using _Formatter_under + = __conditional_t<_S_range_format_is_string, + __format::__formatter_str<_CharT>, + range_formatter<_Vt, _CharT>>; + _Formatter_under _M_under; + }; #endif // C++23 formatting ranges +#undef _GLIBCXX_WIDEN _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/std/forward_list b/libstdc++-v3/include/std/forward_list index 166fdb0..d478851 100644 --- a/libstdc++-v3/include/std/forward_list +++ b/libstdc++-v3/include/std/forward_list @@ -49,6 +49,7 @@ #define __glibcxx_want_algorithm_default_value_type #define __glibcxx_want_allocator_traits_is_always_equal +#define __glibcxx_want_containers_ranges #define __glibcxx_want_erase_if #define __glibcxx_want_incomplete_container_elements #define __glibcxx_want_list_remove_return_type diff --git a/libstdc++-v3/include/std/list b/libstdc++-v3/include/std/list index 170499d..2ba0599 100644 --- a/libstdc++-v3/include/std/list +++ b/libstdc++-v3/include/std/list @@ -73,6 +73,7 @@ #define __glibcxx_want_algorithm_default_value_type #define __glibcxx_want_allocator_traits_is_always_equal +#define __glibcxx_want_containers_ranges #define __glibcxx_want_erase_if #define __glibcxx_want_incomplete_container_elements #define __glibcxx_want_list_remove_return_type diff --git a/libstdc++-v3/include/std/map b/libstdc++-v3/include/std/map index 16a397f..6bfb538 100644 --- a/libstdc++-v3/include/std/map +++ b/libstdc++-v3/include/std/map @@ -72,6 +72,7 @@ #endif #define __glibcxx_want_allocator_traits_is_always_equal +#define __glibcxx_want_containers_ranges #define __glibcxx_want_erase_if #define __glibcxx_want_generic_associative_lookup #define __glibcxx_want_map_try_emplace diff --git a/libstdc++-v3/include/std/numeric b/libstdc++-v3/include/std/numeric index 4d36fcd..490963e 100644 --- a/libstdc++-v3/include/std/numeric +++ b/libstdc++-v3/include/std/numeric @@ -732,12 +732,11 @@ namespace __detail /// @} group numeric_ops #endif // C++17 +#if __glibcxx_ranges_iota >= 202202L // C++ >= 23 namespace ranges { -#if __glibcxx_ranges_iota >= 202202L // C++ >= 23 - template<typename _Out, typename _Tp> - using iota_result = out_value_result<_Out, _Tp>; + using iota_result = out_value_result<_Out, _Tp>; struct __iota_fn { @@ -762,9 +761,8 @@ namespace ranges }; inline constexpr __iota_fn iota{}; - -#endif // __glibcxx_ranges_iota } // namespace ranges +#endif // __glibcxx_ranges_iota _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/std/queue b/libstdc++-v3/include/std/queue index c06a4c3..74b6c07 100644 --- a/libstdc++-v3/include/std/queue +++ b/libstdc++-v3/include/std/queue @@ -68,6 +68,7 @@ #include <bits/stl_queue.h> #define __glibcxx_want_adaptor_iterator_pair_constructor +#define __glibcxx_want_containers_ranges #include <bits/version.h> #endif /* _GLIBCXX_QUEUE */ diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index 7a339c5..9300c36 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -64,7 +64,6 @@ #define __glibcxx_want_ranges_chunk #define __glibcxx_want_ranges_chunk_by #define __glibcxx_want_ranges_enumerate -#define __glibcxx_want_ranges_iota #define __glibcxx_want_ranges_join_with #define __glibcxx_want_ranges_repeat #define __glibcxx_want_ranges_slide diff --git a/libstdc++-v3/include/std/set b/libstdc++-v3/include/std/set index 2ebf485..cf7057a 100644 --- a/libstdc++-v3/include/std/set +++ b/libstdc++-v3/include/std/set @@ -72,6 +72,7 @@ #endif #define __glibcxx_want_allocator_traits_is_always_equal +#define __glibcxx_want_containers_ranges #define __glibcxx_want_erase_if #define __glibcxx_want_generic_associative_lookup #define __glibcxx_want_node_extract diff --git a/libstdc++-v3/include/std/stack b/libstdc++-v3/include/std/stack index 2f7951a..5cea476 100644 --- a/libstdc++-v3/include/std/stack +++ b/libstdc++-v3/include/std/stack @@ -65,6 +65,7 @@ #include <bits/stl_stack.h> #define __glibcxx_want_adaptor_iterator_pair_constructor +#define __glibcxx_want_containers_ranges #include <bits/version.h> #endif /* _GLIBCXX_STACK */ diff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string index 6211da9..7186471 100644 --- a/libstdc++-v3/include/std/string +++ b/libstdc++-v3/include/std/string @@ -60,6 +60,7 @@ #define __glibcxx_want_allocator_traits_is_always_equal #define __glibcxx_want_constexpr_char_traits #define __glibcxx_want_constexpr_string +#define __glibcxx_want_containers_ranges #define __glibcxx_want_erase_if #define __glibcxx_want_nonmember_container_access #define __glibcxx_want_string_resize_and_overwrite diff --git a/libstdc++-v3/include/std/unordered_map b/libstdc++-v3/include/std/unordered_map index 37f2273..3ae25d7 100644 --- a/libstdc++-v3/include/std/unordered_map +++ b/libstdc++-v3/include/std/unordered_map @@ -49,6 +49,7 @@ #endif #define __glibcxx_want_allocator_traits_is_always_equal +#define __glibcxx_want_containers_ranges #define __glibcxx_want_erase_if #define __glibcxx_want_generic_unordered_lookup #define __glibcxx_want_node_extract diff --git a/libstdc++-v3/include/std/unordered_set b/libstdc++-v3/include/std/unordered_set index 4c73e5d..b561163 100644 --- a/libstdc++-v3/include/std/unordered_set +++ b/libstdc++-v3/include/std/unordered_set @@ -49,6 +49,7 @@ #endif #define __glibcxx_want_allocator_traits_is_always_equal +#define __glibcxx_want_containers_ranges #define __glibcxx_want_erase_if #define __glibcxx_want_generic_unordered_lookup #define __glibcxx_want_node_extract diff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector index 8bb2543..a98ffb1 100644 --- a/libstdc++-v3/include/std/vector +++ b/libstdc++-v3/include/std/vector @@ -81,6 +81,7 @@ #define __glibcxx_want_algorithm_default_value_type #define __glibcxx_want_allocator_traits_is_always_equal #define __glibcxx_want_constexpr_vector +#define __glibcxx_want_containers_ranges #define __glibcxx_want_erase_if #define __glibcxx_want_incomplete_container_elements #define __glibcxx_want_nonmember_container_access |