[PATCH] libstdc++: Expose translation related context in format_contexts.
Tomasz Kaminski
tkaminsk@redhat.com
Tue Apr 7 14:36:55 GMT 2026
To give context, to below question, I think I need some guidance and
decision, if we
find drawbacks we discussed acceptable, and want just simpler
implementation.
On Tue, Apr 7, 2026 at 4:30 PM Tomasz Kaminski <tkaminsk@redhat.com> wrote:
> Do you want me to provide an alternative patch, that exports the
> definition for __do_vformat only
> for TUs that use unicode literal encoding?
>
I plan to do that by having something like:
+ template<typename _CharT, bool =
__unicode::__literal_is_unicode<_CharT>()>
+ _Sink_iter<_CharT>
+ __do_vformat_to(_Sink_iter<_CharT> __out, basic_string_view<_CharT>
__fmt,
+ __format_context<_CharT>& __ctx)
And then providing extern definition only for <char, true> and <wchar_t,
true> overloads
of above. (And not introducing any runtime _Api_ctx).
And then once we call C++23 stable, we will export the C++23 version of
above,
and remove C++20 one.
> On Tue, Apr 7, 2026 at 4:08 PM Tomasz Kaminski <tkaminsk@redhat.com>
> wrote:
>
>>
>>
>> On Tue, Apr 7, 2026 at 3:54 PM Jonathan Wakely <jwakely.gcc@gmail.com>
>> wrote:
>>
>>>
>>>
>>> On Tue, 7 Apr 2026, 14:30 Tomasz Kaminski, <tkaminsk@redhat.com> wrote:
>>>
>>>>
>>>>
>>>> On Tue, Apr 7, 2026 at 3:00 PM Jonathan Wakely <jwakely.gcc@gmail.com>
>>>> wrote:
>>>>
>>>>>
>>>>>
>>>>> On Tue, 7 Apr 2026, 09:15 Tomasz Kamiński, <tkaminsk@redhat.com>
>>>>> wrote:
>>>>>
>>>>>> This patch adds a _M_api member to basic_format_context and
>>>>>> basic_format_parse_context, that represents the information about
>>>>>> the TU in which the call was compiled:
>>>>>> * _M_ver represents the C++ standard in which TU was compiled,
>>>>>> * _M_literal_unicode is true when TU was compiled with Unicode
>>>>>> literal encoding,
>>>>>> * _M_liter_enc is reserved for storing text_encoding::id value
>>>>>> for literal encoding, currently set to zero.
>>>>>> This values are then populated by __current_api<_CharT>() functions.
>>>>>>
>>>>>> This would allow the formatter instantiations compiled in different
>>>>>> TU (for example as part of libstdc++.so) to properly handle:
>>>>>> * multi-byte fill-characters used as fill in format-spec, that
>>>>>> are supported only if literal encoding is Unicode,
>>>>>> * '?' as format flags for string and characters, that is only
>>>>>> supported since C++23,
>>>>>> * escaping of the string parameters, that depends on the literal
>>>>>> encoding.
>>>>>>
>>>>>> The further aid the above, a new __do_vformat_to overload is
>>>>>> extracted.
>>>>>> This overload format_context& that encodes the TU-specific properties,
>>>>>> and can be exported in from libstdc++.
>>>>>>
>>>>>> This patch on purpose does not modify the formatters code, and only
>>>>>> adds new members, as adding them later would be ABI break.
>>>>>>
>>>>>> libstdc++-v3/ChangeLog:
>>>>>>
>>>>>> * include/std/format (__format::_Api_ctx,
>>>>>> __format::__current_api):
>>>>>> Define.
>>>>>> (basic_format_parse_context::_M_api): Define.
>>>>>> (basic_format_parse_context::basic_format_parse_context):
>>>>>> Provide (basic_string_view, size_t) constructor only in C++20.
>>>>>> Define new internal private cosntructor accepting _Api_ctx.
>>>>>> (basic_format_context::_M_api): Define.
>>>>>> (basic_format_context::basic_format_context): Add additional
>>>>>> _Api_ctx parameter.
>>>>>> (_Scanner::_Scanner): Add additional _Api_ctx parameter,
>>>>>> and forward it to basic_format_parse_context.
>>>>>> (_Formatting_scanner::_Formatting_scanner): Propagate
>>>>>> _M_api from basic_format_context.
>>>>>> (_Checking_scanner::_Checking_scanner): Use
>>>>>> __format::__current_api()
>>>>>> to initialize API.
>>>>>> (__format::__do_vformat_to): Extract overload accepting
>>>>>> basic_format_context.
>>>>>> ---
>>>>>> I have realized that exporting the vformat specializations correclty
>>>>>> requires
>>>>>> much bigger code changes, than I am comfortable making this late in
>>>>>> the stage-4,
>>>>>> as we will need to make the code independed on TU specific properties
>>>>>> (like
>>>>>> encodinds). This patch instead adds a context members to
>>>>>> basic_format_context
>>>>>> and basic_format_parse_context that would allow doing so in the
>>>>>> future.
>>>>>>
>>>>>
>>>>> An alternative would be to have an inline dispatching function that
>>>>> decides whether the current TU matches what's in the library (where that
>>>>> will be the common case) and only uses the explicit instantiations of it
>>>>> matches.
>>>>>
>>>> Seems reasonable for unicode encoding, but does not solve multiple
>>>> standard.
>>>>
>>>>>
>>>>> I'm not sure this is really a problem I care about solving. If you try
>>>>> to mix incompatible literal encodings in one program you shouldn't expect
>>>>> sensible results for code that is sensitive to the literal encoding.
>>>>>
>>>>> When mixing C++20 and C++23, the C++20 TUs should use the explicit
>>>>> instantiation which is right for C++20, and C++23 TUs will use an implicit
>>>>> instantiation of the C++23 definition.
>>>>>
>>>> This works only on surface level, C++20 will use __vformat_impl_20 and
>>>> C++23 will use __vformat_impl_23, defined in format-inst-20, format-inst-23
>>>> source files.
>>>>
>>>
>>> Once we stabilise C++23 I think we should only instantiate the format
>>> functions for C++23. Will anybody really care if they use a dynamic format
>>> string in C++20 code and don't get an exception for using a C++23 format
>>> specifier?
>>>
>> Yes, the fact that the format specifier string is accepted by `vformat`
>> but rejected by `format` seems very surprising to me, but if we accepted
>> that we have a much simpler problem to solve. If we plan to accept all
>> C++23 specifiers for basic types as extension in C++20 mode, once
>> it will be stabilized, then that would sound much more intuitive for me.
>>
>>>
>>> Both of these files will instantiate `__formatter_str` under the same
>>>> name. When they are combined into `libstdc++.so`, linker one, and one
>>>> standard
>>>> will get incorrect behavior for one of the standards.
>>>>
>>>
>>> Fine, the older standard could get the "wrong" behaviour (where wrong
>>> just means supporting C++23 features when called from C++20 TUs).
>>>
>> I considered that unacceptable, and we even have a test cases checking if
>> that is the case. The failures for these tests were the reason
>> I started exploring alternatives.
>>
>>>
>>> To avoid this problem we will need to ABI tag each used formatter in
>>>> some manner and apply that
>>>> tag virally to any formatter referenced from these functions.
>>>>
>>>>
>>>>>
>>>>> Is there really a problem?
>>>>>
>>>>> If we can capture the API level without adding any overhead, I suppose
>>>>> that's acceptable.
>>>>>
>>>>> If we store the text encoding, what are we going to do with it? Use
>>>>> iconv to convert the fill character on the fly? To what output encoding?
>>>>>
>>>> This if for future, if we want to handle string escaping for
>>>> non-unicode encoding better than giving them equivalent behavior than ASCII.
>>>> We can add any additional fields to basic_format_parse_context and
>>>> basic_format_context in the future; this is why I am reserving space for it.
>>>>
>>>> // Also could you take a look at:
>>>> https://gcc.gnu.org/pipermail/libstdc++/2026-April/066030.html
>>>>
>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> Tested all *format* test on x86_64-linux. OK for trunk when all test
>>>>>> passes?
>>>>>>
>>>>>> libstdc++-v3/include/std/format | 209
>>>>>> ++++++++++++++++++++------------
>>>>>> 1 file changed, 133 insertions(+), 76 deletions(-)
>>>>>>
>>>>>> diff --git a/libstdc++-v3/include/std/format
>>>>>> b/libstdc++-v3/include/std/format
>>>>>> index eca5bd213aa..97d1ecb3ed6 100644
>>>>>> --- a/libstdc++-v3/include/std/format
>>>>>> +++ b/libstdc++-v3/include/std/format
>>>>>> @@ -140,6 +140,37 @@ namespace __format
>>>>>> template<typename, typename...> friend struct
>>>>>> std::basic_format_string;
>>>>>> };
>>>>>>
>>>>>> + // Exposed via basic_format_parse_context, defines the TU specific
>>>>>> information
>>>>>> + // like encoding and standard version.
>>>>>> + struct _Api_ctx
>>>>>> + {
>>>>>> + enum class _Version : unsigned char
>>>>>> + { _Api_2020, _Api_2023, _Api_2026 };
>>>>>> +
>>>>>> + _Version _M_ver;
>>>>>> + unsigned _M_unused : 23;
>>>>>> + unsigned _M_literal_unicode : 1;
>>>>>> + __INT_LEAST32_TYPE__ _M_literal_enc;
>>>>>> + };
>>>>>> + using enum _Api_ctx::_Version;
>>>>>> +
>>>>>> + template<typename _CharT>
>>>>>> + constexpr _Api_ctx
>>>>>> + __current_api()
>>>>>>
>>>>>
>>>>> Should this be always inline?
>>>>>
>>>>> + {
>>>>>> + _Api_ctx __api{};
>>>>>> +#if __cpluplus > 202302L
>>>>>> + __api._M_ver = _Api_2026;
>>>>>> +#elif __cpluplus > 202002L
>>>>>> + __api._M_ver = _Api_2023;
>>>>>> +#else
>>>>>> + __api._M_ver = _Api_2020;
>>>>>> +#endif
>>>>>> + __api._M_literal_unicode
>>>>>> + = __unicode::__literal_encoding_is_unicode<_CharT>();
>>>>>> + return __api;
>>>>>> + }
>>>>>> +
>>>>>> } // namespace __format
>>>>>> /// @endcond
>>>>>>
>>>>>> @@ -274,7 +305,7 @@ namespace __format
>>>>>> { __throw_format_error("format error: failed to parse
>>>>>> format-spec"); }
>>>>>>
>>>>>> template<typename _CharT> class _Scanner;
>>>>>> -
>>>>>> + template<typename _Out, typename _CharT> class _Formatting_scanner;
>>>>>> } // namespace __format
>>>>>> /// @endcond
>>>>>>
>>>>>> @@ -408,23 +439,34 @@ namespace __format
>>>>>> // This must not be constexpr.
>>>>>> static void __invalid_dynamic_spec(const char*);
>>>>>>
>>>>>> - friend __format::_Scanner<_CharT>;
>>>>>> -#endif
>>>>>> -
>>>>>> +#else
>>>>>> // This constructor should only be used by the implementation.
>>>>>> constexpr explicit
>>>>>> basic_format_parse_context(basic_string_view<_CharT> __fmt,
>>>>>> size_t __num_args) noexcept
>>>>>> : _M_begin(__fmt.begin()), _M_end(__fmt.end()),
>>>>>> _M_num_args(__num_args)
>>>>>> { }
>>>>>> +#endif
>>>>>>
>>>>>> private:
>>>>>> + // This constructor should only be used by the implementation.
>>>>>> + constexpr explicit
>>>>>> + basic_format_parse_context(__format::_Api_ctx __api,
>>>>>> + basic_string_view<_CharT> __fmt,
>>>>>> + size_t __num_args) noexcept
>>>>>> + : _M_api(__api), _M_begin(__fmt.begin()), _M_end(__fmt.end())
>>>>>> + , _M_num_args(__num_args)
>>>>>> + { }
>>>>>> +
>>>>>> + __format::_Api_ctx _M_api = __format::__current_api<_CharT>();
>>>>>>
>>>>>
>>>>> What guarantees this will be initialized by a call to the right
>>>>> version?
>>>>>
>>>> This is only used by basic_format_parse_context(string) constructor,
>>>> that is mostly used
>>>> for user defined-formatters. We may want to define this cosntructors as
>>>> always inline.
>>>>
>>>>>
>>>>> Doesn't putting this member first add a lot of wasted padding due to
>>>>> alignment?
>>>>>
>>>> I do not think basic_format_parse_context and basic_format_context size
>>>> is relevant to
>>>> anybody. But the struct is 64bits, so should not add extra pading.
>>>>
>>>
>>> I don't understand how adding a new byte before the first iterator
>>> member doesn't introduce sizeof(void*)-1 bytes of padding.
>>>
>> _Api_ctx is 8B struct with the literal encoding information. And I
>> considered having a spare bytes there as a feature, and not
>> a drawback.
>>
>>>
>>> Why don't we just give _Indexing a fixed underlying type of unsigned
>>> char and then put the API version after that?
>>>
>>>
>>>
>>>
>>>>>
>>>>> iterator _M_begin;
>>>>>> iterator _M_end;
>>>>>> enum _Indexing { _Unknown, _Manual, _Auto };
>>>>>> _Indexing _M_indexing = _Unknown;
>>>>>>
>>>>>
>>>>> We already have padding bytes here (and could guarantee that by giving
>>>>> a fixed underlying type to _Indexing)
>>>>>
>>>>> size_t _M_next_arg_id = 0;
>>>>>> size_t _M_num_args = 0;
>>>>>> +
>>>>>> + friend __format::_Scanner<_CharT>;
>>>>>> };
>>>>>>
>>>>>> /// @cond undocumented
>>>>>> @@ -4927,18 +4969,21 @@ namespace __format
>>>>>> {
>>>>>> static_assert( output_iterator<_Out, const _CharT&> );
>>>>>>
>>>>>> + __format::_Api_ctx _M_api;
>>>>>> basic_format_args<basic_format_context> _M_args;
>>>>>> _Out _M_out;
>>>>>> __format::_Optional_locale _M_loc;
>>>>>>
>>>>>> - basic_format_context(basic_format_args<basic_format_context>
>>>>>> __args,
>>>>>> + basic_format_context(__format::_Api_ctx __api,
>>>>>> + basic_format_args<basic_format_context>
>>>>>> __args,
>>>>>> _Out __out)
>>>>>> - : _M_args(__args), _M_out(std::move(__out))
>>>>>> + : _M_api(__api), _M_args(__args), _M_out(std::move(__out))
>>>>>> { }
>>>>>>
>>>>>> - basic_format_context(basic_format_args<basic_format_context>
>>>>>> __args,
>>>>>> + basic_format_context(__format::_Api_ctx __api,
>>>>>> + basic_format_args<basic_format_context>
>>>>>> __args,
>>>>>> _Out __out, const std::locale& __loc)
>>>>>> - : _M_args(__args), _M_out(std::move(__out)), _M_loc(__loc)
>>>>>> + : _M_api(__api), _M_args(__args),
>>>>>> _M_out(std::move(__out)), _M_loc(__loc)
>>>>>> { }
>>>>>>
>>>>>> // _GLIBCXX_RESOLVE_LIB_DEFECTS
>>>>>> @@ -4954,6 +4999,7 @@ namespace __format
>>>>>> const locale*);
>>>>>>
>>>>>> friend __format::__formatter_chrono<_CharT>;
>>>>>> + friend __format::_Formatting_scanner<_Out, _CharT>;
>>>>>>
>>>>>> public:
>>>>>> ~basic_format_context() = default;
>>>>>> @@ -4998,8 +5044,9 @@ namespace __format
>>>>>> } _M_pc;
>>>>>>
>>>>>> constexpr explicit
>>>>>> - _Scanner(basic_string_view<_CharT> __str, size_t __nargs =
>>>>>> (size_t)-1)
>>>>>> - : _M_pc(__str, __nargs)
>>>>>> + _Scanner(_Api_ctx __api, basic_string_view<_CharT> __str,
>>>>>> + size_t __nargs = (size_t)-1)
>>>>>> + : _M_pc(__api, __str, __nargs)
>>>>>> { }
>>>>>>
>>>>>> constexpr iterator begin() const noexcept { return
>>>>>> _M_pc.begin(); }
>>>>>> @@ -5115,7 +5162,7 @@ namespace __format
>>>>>> public:
>>>>>> _Formatting_scanner(basic_format_context<_Out, _CharT>& __fc,
>>>>>> basic_string_view<_CharT> __str)
>>>>>> - : _Scanner<_CharT>(__str), _M_fc(__fc)
>>>>>> + : _Scanner<_CharT>(__fc._M_api, __str), _M_fc(__fc)
>>>>>> { }
>>>>>>
>>>>>> private:
>>>>>> @@ -5176,7 +5223,8 @@ namespace __format
>>>>>> public:
>>>>>> consteval
>>>>>> _Checking_scanner(basic_string_view<_CharT> __str)
>>>>>> - : _Scanner<_CharT>(__str, sizeof...(_Args))
>>>>>> + : _Scanner<_CharT>(__format::__current_api<_CharT>(),
>>>>>>
>>>>>
>>>>> This is consteval so should use the right version for the current TU.
>>>>>
>>>>> + __str, sizeof...(_Args))
>>>>>> {
>>>>>> #if __cpp_lib_format >= 202305L
>>>>>> this->_M_pc._M_types = _M_types.data();
>>>>>> @@ -5219,82 +5267,91 @@ namespace __format
>>>>>> #endif
>>>>>> };
>>>>>>
>>>>>> - template<typename _Out, typename _CharT, typename _Context>
>>>>>> - inline _Out
>>>>>> - __do_vformat_to(_Out __out, basic_string_view<_CharT> __fmt,
>>>>>> - const basic_format_args<_Context>& __args,
>>>>>> - const locale* __loc)
>>>>>> + template<typename _CharT>
>>>>>> + _Sink_iter<_CharT>
>>>>>> + __do_vformat_to(_Sink_iter<_CharT> __out,
>>>>>> basic_string_view<_CharT> __fmt,
>>>>>> + __format_context<_CharT>& __ctx)
>>>>>> {
>>>>>> - if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
>>>>>> - {
>>>>>> - if constexpr (is_same_v<_CharT, char>)
>>>>>> - // Fast path for "{}" format strings and simple format
>>>>>> arg types.
>>>>>> - if (__fmt.size() == 2 && __fmt[0] == '{' && __fmt[1] ==
>>>>>> '}')
>>>>>> - {
>>>>>> - bool __done = false;
>>>>>> - __format::__visit_format_arg([&](auto& __arg) {
>>>>>> - using _Tp = remove_cvref_t<decltype(__arg)>;
>>>>>> - if constexpr (is_same_v<_Tp, bool>)
>>>>>> + if constexpr (is_same_v<_CharT, char>)
>>>>>> + // Fast path for "{}" format strings and simple format arg
>>>>>> types.
>>>>>> + if (__fmt.size() == 2 && __fmt[0] == '{' && __fmt[1] == '}')
>>>>>> + {
>>>>>> + bool __done = false;
>>>>>> + __format::__visit_format_arg([&](auto& __arg) {
>>>>>> + using _Tp = remove_cvref_t<decltype(__arg)>;
>>>>>> + if constexpr (is_same_v<_Tp, bool>)
>>>>>> + {
>>>>>> + size_t __len = 4 + !__arg;
>>>>>> + const char* __chars[] = { "false", "true" };
>>>>>> + if (auto __res = __out._M_reserve(__len))
>>>>>> {
>>>>>> - size_t __len = 4 + !__arg;
>>>>>> - const char* __chars[] = { "false", "true" };
>>>>>> - if (auto __res = __out._M_reserve(__len))
>>>>>> - {
>>>>>> - __builtin_memcpy(__res.get(),
>>>>>> __chars[__arg], __len);
>>>>>> - __res._M_bump(__len);
>>>>>> - __done = true;
>>>>>> - }
>>>>>> + __builtin_memcpy(__res.get(), __chars[__arg],
>>>>>> __len);
>>>>>> + __res._M_bump(__len);
>>>>>> + __done = true;
>>>>>> }
>>>>>> - else if constexpr (is_same_v<_Tp, char>)
>>>>>> + }
>>>>>> + else if constexpr (is_same_v<_Tp, char>)
>>>>>> + {
>>>>>> + if (auto __res = __out._M_reserve(1))
>>>>>> {
>>>>>> - if (auto __res = __out._M_reserve(1))
>>>>>> - {
>>>>>> - *__res.get() = __arg;
>>>>>> - __res._M_bump(1);
>>>>>> - __done = true;
>>>>>> - }
>>>>>> + *__res.get() = __arg;
>>>>>> + __res._M_bump(1);
>>>>>> + __done = true;
>>>>>> }
>>>>>> - else if constexpr (is_integral_v<_Tp>)
>>>>>> + }
>>>>>> + else if constexpr (is_integral_v<_Tp>)
>>>>>> + {
>>>>>> + make_unsigned_t<_Tp> __uval;
>>>>>> + const bool __neg = __arg < 0;
>>>>>> + if (__neg)
>>>>>> + __uval = make_unsigned_t<_Tp>(~__arg) + 1u;
>>>>>> + else
>>>>>> + __uval = __arg;
>>>>>> + const auto __n = __detail::__to_chars_len(__uval);
>>>>>> + if (auto __res = __out._M_reserve(__n + __neg))
>>>>>> {
>>>>>> - make_unsigned_t<_Tp> __uval;
>>>>>> - const bool __neg = __arg < 0;
>>>>>> - if (__neg)
>>>>>> - __uval = make_unsigned_t<_Tp>(~__arg) + 1u;
>>>>>> - else
>>>>>> - __uval = __arg;
>>>>>> - const auto __n =
>>>>>> __detail::__to_chars_len(__uval);
>>>>>> - if (auto __res = __out._M_reserve(__n + __neg))
>>>>>> - {
>>>>>> - auto __ptr = __res.get();
>>>>>> - *__ptr = '-';
>>>>>> - __detail::__to_chars_10_impl(__ptr +
>>>>>> (int)__neg, __n,
>>>>>> - __uval);
>>>>>> - __res._M_bump(__n + __neg);
>>>>>> - __done = true;
>>>>>> - }
>>>>>> + auto __ptr = __res.get();
>>>>>> + *__ptr = '-';
>>>>>> + __detail::__to_chars_10_impl(__ptr +
>>>>>> (int)__neg, __n,
>>>>>> + __uval);
>>>>>> + __res._M_bump(__n + __neg);
>>>>>> + __done = true;
>>>>>> }
>>>>>> - else if constexpr (is_convertible_v<_Tp,
>>>>>> string_view>)
>>>>>> + }
>>>>>> + else if constexpr (is_convertible_v<_Tp, string_view>)
>>>>>> + {
>>>>>> + string_view __sv = __arg;
>>>>>> + if (auto __res = __out._M_reserve(__sv.size()))
>>>>>> {
>>>>>> - string_view __sv = __arg;
>>>>>> - if (auto __res = __out._M_reserve(__sv.size()))
>>>>>> - {
>>>>>> - __builtin_memcpy(__res.get(), __sv.data(),
>>>>>> __sv.size());
>>>>>> - __res._M_bump(__sv.size());
>>>>>> - __done = true;
>>>>>> - }
>>>>>> + __builtin_memcpy(__res.get(), __sv.data(),
>>>>>> __sv.size());
>>>>>> + __res._M_bump(__sv.size());
>>>>>> + __done = true;
>>>>>> }
>>>>>> - }, __args.get(0));
>>>>>> + }
>>>>>> + }, __ctx.arg(0));
>>>>>>
>>>>>> - if (__done)
>>>>>> - return __out;
>>>>>> - }
>>>>>> + if (__done)
>>>>>> + return __out;
>>>>>> + }
>>>>>>
>>>>>> + _Formatting_scanner<_Sink_iter<_CharT>, _CharT>
>>>>>> __scanner(__ctx, __fmt);
>>>>>> + __scanner._M_scan();
>>>>>> + return __out;
>>>>>> + }
>>>>>> +
>>>>>> + template<typename _Out, typename _CharT, typename _Context>
>>>>>> + _Out
>>>>>> + __do_vformat_to(_Out __out, basic_string_view<_CharT> __fmt,
>>>>>> + const basic_format_args<_Context>& __args,
>>>>>> + const locale* __loc)
>>>>>> + {
>>>>>> + if constexpr (is_same_v<_Out, _Sink_iter<_CharT>>)
>>>>>> + {
>>>>>> + const auto __api = __format::__current_api<_CharT>();
>>>>>> auto __ctx = __loc == nullptr
>>>>>> - ? _Context(__args, __out)
>>>>>> - : _Context(__args, __out, *__loc);
>>>>>> - _Formatting_scanner<_Sink_iter<_CharT>, _CharT>
>>>>>> __scanner(__ctx, __fmt);
>>>>>> - __scanner._M_scan();
>>>>>> - return __out;
>>>>>> + ? _Context(__api, __args, __out)
>>>>>> + : _Context(__api, __args, __out, *__loc);
>>>>>> + return __do_vformat_to(std::move(__out), __fmt, __ctx);
>>>>>> }
>>>>>> else if constexpr (__contiguous_char_iter<_CharT, _Out>)
>>>>>> {
>>>>>> --
>>>>>> 2.53.0
>>>>>>
>>>>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260407/141b68fd/attachment-0001.htm>
More information about the Libstdc++
mailing list