On Wed, May 7, 2025 at 1:01 PM Tomasz Kamiński <tkami...@redhat.com> wrote:
> Formatting code is extracted to _M_format_to function, that produced output > to specified iterator. This function is now invoked either with __fc.out() > directly (if width is not specified) or _Padding_sink::out(). > > This avoid formatting to temporary string if no padding is requested, > and minimize allocations otherwise. For more details see commit message of > r16-142-g01e5ef3e8b91288f5d387a27708f9f8979a50edf. > > This should not increase number of instantiations, as implementation only > produce basis_format_context with _Sink_iter as iterator, which is also > _Padding_sink iterator. > > libstdc++-v3/ChangeLog: > > * include/bits/chrono_io.h (__formatter_chrono::_M_format_to): > Extracted from _M_format. > (__formatter_chrono::_M_format): Use _Padding_sink and delegate > to _M_format_to. > --- > I have checked that there are no other calls to out() in this file, > so _M_format_to uses only __out, and not iterator from __fc. > Testing on x86_64-linux. OK for trunk? > All test passed. > > libstdc++-v3/include/bits/chrono_io.h | 55 ++++++++++----------------- > 1 file changed, 20 insertions(+), 35 deletions(-) > > diff --git a/libstdc++-v3/include/bits/chrono_io.h > b/libstdc++-v3/include/bits/chrono_io.h > index 620227a9f35..ace8b9f2629 100644 > --- a/libstdc++-v3/include/bits/chrono_io.h > +++ b/libstdc++-v3/include/bits/chrono_io.h > @@ -503,9 +503,7 @@ namespace __format > _M_format(const _Tp& __t, _FormatContext& __fc, > bool __is_neg = false) const > { > - auto __first = _M_spec._M_chrono_specs.begin(); > - const auto __last = _M_spec._M_chrono_specs.end(); > - if (__first == __last) > + if (_M_spec._M_chrono_specs.empty()) > return _M_format_to_ostream(__t, __fc, __is_neg); > > #if defined _GLIBCXX_USE_NL_LANGINFO_L && __CHAR_BIT__ == 8 > @@ -525,29 +523,29 @@ namespace __format > __fc._M_loc = __with_encoding_conversion(__loc); > } > #endif > - > - _Sink_iter<_CharT> __out; > - __format::_Str_sink<_CharT> __sink; > - bool __write_direct = false; > - if constexpr (is_same_v<typename _FormatContext::iterator, > - _Sink_iter<_CharT>>) > - { > - if (_M_spec._M_width_kind == __format::_WP_none) > - { > - __out = __fc.out(); > - __write_direct = true; > - } > - else > - __out = __sink.out(); > - } > - else > - __out = __sink.out(); > - > // formatter<duration> passes the correct value of __is_neg > // for durations but for hh_mm_ss we decide it here. > if constexpr (__is_specialization_of<_Tp, chrono::hh_mm_ss>) > __is_neg = __t.is_negative(); > > + const size_t __padwidth = _M_spec._M_get_width(__fc); > + if (__padwidth == 0) > + return _M_format_to(__t, __fc.out(), __fc, __is_neg); > + > + using _Out = typename _FormatContext::iterator; > + _Padding_sink<_Out, _CharT> __sink(__fc.out(), __padwidth); > + _M_format_to(__t, __sink.out(), __fc, __is_neg); > + return __sink._M_finish(_M_spec._M_align, _M_spec._M_fill); > + } > + > + template<typename _Tp, typename _Out, typename _FormatContext> > + _Out > + _M_format_to(const _Tp& __t, _Out __out, _FormatContext& __fc, > + bool __is_neg) const > + { > + auto __first = _M_spec._M_chrono_specs.begin(); > + const auto __last = _M_spec._M_chrono_specs.end(); > + > auto __print_sign = [&__is_neg, &__out] { > if constexpr (chrono::__is_duration_v<_Tp> > || __is_specialization_of<_Tp, > chrono::hh_mm_ss>) > @@ -699,20 +697,7 @@ namespace __format > } > } > while (__first != __last); > - > - if constexpr (is_same_v<typename _FormatContext::iterator, > - _Sink_iter<_CharT>>) > - if (__write_direct) > - return __out; > - > - auto __str = __sink.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, _M_spec); > + return std::move(__out); > } > > _ChronoSpec<_CharT> _M_spec; > -- > 2.49.0 > >