[PATCH 1/4] libstdc++: Format empty chrono-spec for the calendar types directly.
Jonathan Wakely
jwakely@redhat.com
Thu Jun 12 11:37:55 GMT 2025
On 09/06/25 13:14 +0200, Tomasz Kaminski wrote:
>On Fri, Jun 6, 2025 at 1:02 PM Tomasz Kamiński <tkaminsk@redhat.com> wrote:
>
>> This patch change implementation of the formatters for the calendar types,
>> so they no longer delegate to operator<< for ostream in case of empty
>> chrono-spec.
>> Instead of that, we define the behavior of the in terms of format
>> specifiers,
>> that format specifiers are supplied by each formatter as argument to
>> _M_parse
>> Similary is formatter constructor it's __formatter_chrono from revalant
>> default
>> spec, so we preserve functionality of calling format on default cosntructed
>> formatters.
>>
>> Expressing the existing functionality of the operaetor ostream, requires
>> providing two additional features:
>> * printing "is not a valid sth" for !ok objects,
>> * printing a weekday index in the month.
>>
>> The formatter functionality is enabled by setting spec _M_debug
>> (corresponding
>> to '?') that is currently unused. This is currently supported only for
>> subset of format specifiers used by the ostream operators. In future, we
>> could
>> make this user configurable (by adding '?' after 'L') and cover all flags.
>>
>> For the handling of the weekday index (for weekday_indexed, month_weekday,
>> year_month_weekday), we need to introduce an new format specifier. To not
>> conflict with future extension we use '%\0' (embedded null) as this
>> character
>> cannot be placed in valid format spec.
>>
>> Finally, the format strings for calendar types subsets each other, e.g.
>> year_month_weekday_last ("%Y/%b/%a[last])" contains month_weekday_last,
>> weekday_last, weekday, e.t.c.. We introduce a _ChronoFormats class that
>> provide
>> consteval accessors to format specs, internally sharing they
>> representations.
>>
>> libstdc++-v3/ChangeLog:
>>
>> * include/bits/chrono_io.h (__format::_ChronoFormats): Define.
>> (__formatter_chrono::__formatter_chrono())
>> (__formatter_chrono::__formatter_chrono(_ChronoSpec<_CharT>)):
>> Define.
>> (__formatter_chrono::_M_parse): Add parameter with default spec,
>> namd merge it with new values. Handle '%\0' as weekday index
>> specifier.
>> (__formatter_chrono::_M_a_A, __formatter_chrono::_M_b_B)
>> (__formatter_chrono::_M_C_y_Y, __formatter_chrono::_M_d_e)
>> (__formatter_chrono::_M_F): Support _M_debug flag.
>> (__formatter_chrono::_M_wi, __formatter_chrono::_S_weekday_index):
>> Define.
>> (std::formatter<chrono::day, _CharT>)
>> (std::formatter<chrono::month, _CharT>)
>> (std::formatter<chrono::year, _CharT>)
>> (std::formatter<chrono::weekday, _CharT>)
>> (std::formatter<chrono::weekday_indexed, _CharT>)
>> (std::formatter<chrono::weekday_last, _CharT>)
>> (std::formatter<chrono::month_day, _CharT>)
>> (std::formatter<chrono::month_day_last, _CharT>)
>> (std::formatter<chrono::month_weekday, _CharT>)
>> (std::formatter<chrono::month_weekday_last, _CharT>)
>> (std::formatter<chrono::year_month, _CharT>)
>> (std::formatter<chrono::year_month_day, _CharT>)
>> (std::formatter<chrono::year_month_day_last, _CharT>)
>> (std::formatter<chrono::year_month_weekday, _CharT>)
>> (std::formatter<chrono::year_month_weekday_last, _CharT>):
>> Define __defSpec, and pass it as argument to _M_prase and
>> constructor of __formatter_chrono.
>> ---
>> libstdc++-v3/include/bits/chrono_io.h | 430 +++++++++++++++++++++++---
>> 1 file changed, 381 insertions(+), 49 deletions(-)
>>
>> diff --git a/libstdc++-v3/include/bits/chrono_io.h
>> b/libstdc++-v3/include/bits/chrono_io.h
>> index c5c5e4bae53..e36cf1ffd31 100644
>> --- a/libstdc++-v3/include/bits/chrono_io.h
>> +++ b/libstdc++-v3/include/bits/chrono_io.h
>> @@ -238,6 +238,93 @@ namespace __format
>> operator|=(_ChronoParts& __x, _ChronoParts __y) noexcept
>> { return __x = __x | __y; }
>>
>> + template<typename _CharT>
>> + struct _ChronoFormats
>> + {
>> + using _String_view = basic_string_view<_CharT>;
>> +
>> + static consteval
>> + _String_view
>> + _S_f() noexcept
>> + { return _GLIBCXX_WIDEN("%F"); }
>> +
>> + static consteval
>> + _String_view
>> + _S_ymd() noexcept
>> + { return _GLIBCXX_WIDEN("%Y/%b/%d"); }
>> +
>> + static consteval
>> + _String_view
>> + _S_ym() noexcept
>> + { return _S_ymd().substr(0, 5); }
>> +
>> + static consteval
>> + _String_view
>> + _S_md() noexcept
>> + { return _S_ymd().substr(3); }
>> +
>> + static consteval
>> + _String_view
>> + _S_y() noexcept
>> + { return _S_ymd().substr(0, 2); }
>> +
>> + static consteval
>> + _String_view
>> + _S_m() noexcept
>> + { return _S_ymd().substr(3, 2); }
>> +
>> + static consteval
>> + _String_view
>> + _S_d() noexcept
>> + { return _S_ymd().substr(6, 2); }
>> +
>> + static consteval
>> + _String_view
>> + _S_ymwi() noexcept
>> + // %\0 is extension for handling weekday index
>> + { return _String_view(_GLIBCXX_WIDEN("%Y/%b/%a[%\0]"), 12); }
>> +
>> + static consteval
>> + _String_view
>> + _S_mwi() noexcept
>> + { return _S_ymwi().substr(3); }
>> +
>> + static consteval
>> + _String_view
>> + _S_wi() noexcept
>> + { return _S_ymwi().substr(6); }
>> +
>> + static consteval
>> + _String_view
>> + _S_w() noexcept
>> + { return _S_ymwi().substr(6, 2); }
>> +
>> + static consteval
>> + _String_view
>> + _S_ymwl() noexcept
>> + { return _GLIBCXX_WIDEN("%Y/%b/%a[last]"); }
>> +
>> + static consteval
>> + _String_view
>> + _S_mwl() noexcept
>> + { return _S_ymwl().substr(3); }
>> +
>> + static consteval
>> + _String_view
>> + _S_wl() noexcept
>> + { return _S_ymwl().substr(6); }
>> +
>> + static consteval
>> + _String_view
>> + _S_yml() noexcept
>> + { return _GLIBCXX_WIDEN("%Y/%b/last"); }
>> +
>> + static consteval
>> + _String_view
>> + _S_ml() noexcept
>> + { return _S_yml().substr(3); }
>> + };
>> +
>> // TODO rename this to chrono::__formatter? or
>> chrono::__detail::__formatter?
>> template<typename _CharT>
>> struct __formatter_chrono
>> @@ -245,49 +332,69 @@ namespace __format
>> using __string_view = basic_string_view<_CharT>;
>> using __string = basic_string<_CharT>;
>>
>> + __formatter_chrono() = default;
>> +
>> + constexpr explicit
>> + __formatter_chrono(_ChronoSpec<_CharT> __spec) noexcept
>> + : _M_spec(__spec)
>> + { }
>> +
>> template<typename _ParseContext>
>> constexpr typename _ParseContext::iterator
>> - _M_parse(_ParseContext& __pc, _ChronoParts __parts)
>> + _M_parse(_ParseContext& __pc, _ChronoParts __parts,
>> + const _ChronoSpec<_CharT>& __def = {})
>> {
>> auto __first = __pc.begin();
>> auto __last = __pc.end();
>>
>> _ChronoSpec<_CharT> __spec{};
>>
>This part could also be implemented as, let me know which version do you
>prefer:
I think I prefer this version, doing __spec = __def;
Rest of the review coming soon ...
> using __string_view = basic_string_view<_CharT>;
> using __string = basic_string<_CharT>;
>
>+ __formatter_chrono() = default;
>+
>+ constexpr explicit
>+ __formatter_chrono(_ChronoSpec<_CharT> __spec) noexcept
>+ : _M_spec(__spec)
>+ { }
>+
> template<typename _ParseContext>
> constexpr typename _ParseContext::iterator
>- _M_parse(_ParseContext& __pc, _ChronoParts __parts)
>+ _M_parse(_ParseContext& __pc, _ChronoParts __parts,
>+ const _ChronoSpec<_CharT>& __def = {})
> {
> auto __first = __pc.begin();
> auto __last = __pc.end();
>
>- _ChronoSpec<_CharT> __spec{};
>+ _ChronoSpec<_CharT> __spec = __def;
>
> auto __finalize = [this, &__spec] {
> _M_spec = __spec;
>@@ -285,6 +380,7 @@ namespace __format
> return __first;
> }
>
>+ __spec._M_localized = false;
> __first = __spec._M_parse_locale(__first, __last);
> if (__finished())
> return __first;
>@@ -307,6 +403,7 @@ namespace __format
> // against __parts (so fail for %Y if no year in parts).
> // Save range in __spec._M_chrono_specs.
>
>+ __spec._M_debug = false;
> const auto __chrono_specs = __first++; // Skip leading '%'
> if (*__chrono_specs != '%')
> __throw_format_error("chrono format error: no '%' at
>
>>
>> - auto __finalize = [this, &__spec] {
>> - _M_spec = __spec;
>> + auto __apply_default = [&] {
>> + _M_spec = __def;
>> + if (__spec._M_align != _Align_default)
>> + {
>> + _M_spec._M_align = __spec._M_align;
>> + _M_spec._M_fill = __spec._M_fill;
>> + }
>> + if (__spec._M_width_kind != _WP_none)
>> + {
>> + _M_spec._M_width_kind = __spec._M_width_kind;
>> + _M_spec._M_width = __spec._M_width;
>> + }
>> + if (__spec._M_prec_kind != _WP_none)
>> + {
>> + _M_spec._M_prec_kind = __spec._M_prec_kind;
>> + _M_spec._M_prec = __spec._M_prec;
>> + }
>> + _M_spec._M_localized |= __spec._M_localized;
>> + return __first;
>> };
>>
>> auto __finished = [&] {
>> - if (__first == __last || *__first == '}')
>> - {
>> - __finalize();
>> - return true;
>> - }
>> - return false;
>> + return __first == __last || *__first == '}';
>> };
>>
>> if (__finished())
>> - return __first;
>> + return __apply_default();
>>
>> __first = __spec._M_parse_fill_and_align(__first, __last);
>> if (__finished())
>> - return __first;
>> + return __apply_default();
>>
>> __first = __spec._M_parse_width(__first, __last, __pc);
>> if (__finished())
>> - return __first;
>> + return __apply_default();
>>
>> if (__parts & _ChronoParts::_Duration)
>> {
>> __first = __spec._M_parse_precision(__first, __last, __pc);
>> if (__finished())
>> - return __first;
>> + return __apply_default();
>> }
>>
>> __first = __spec._M_parse_locale(__first, __last);
>> if (__finished())
>> - return __first;
>> + return __apply_default();
>>
>> // Everything up to the end of the string or the first '}' is a
>> // chrono-specs string. Check it is valid.
>> @@ -562,6 +669,10 @@ namespace __format
>> _CharT __c = *__first++;
>> switch (__c)
>> {
>> + // %\0 is extension for handling weekday index
>> + case '\0':
>> + __out = _M_wi(__t, std::move(__out), __fc);
>> + break;
>> case 'a':
>> case 'A':
>> __out = _M_a_A(__t, std::move(__out), __fc, __c == 'A');
>> @@ -816,6 +927,22 @@ namespace __format
>> return __format::__write(std::move(__out), __s);
>> }
>>
>> + template<typename _Tp, typename _FormatContext>
>> + typename _FormatContext::iterator
>> + _M_wi(const _Tp& __t, typename _FormatContext::iterator __out,
>> + _FormatContext& __ctx) const
>> + {
>> + // %\0 Extension to format weekday index, used only by empty
>> format spec
>> + unsigned __wi = _S_weekday_index(__t);
>> +
>> + _CharT __buf[3];
>> + __out = __format::__write(std::move(__out), _S_str_d1(__buf,
>> __wi));
>> + if (_M_spec._M_debug && (__wi < 1 || __wi > 5))
>> + __out = __format::__write(std::move(__out),
>> + __string_view(_GLIBCXX_WIDEN(" is not a valid
>> index")));
>> + return std::move(__out);
>> + }
>> +
>> template<typename _Tp, typename _FormatContext>
>> typename _FormatContext::iterator
>> _M_a_A(const _Tp& __t, typename _FormatContext::iterator __out,
>> @@ -825,7 +952,16 @@ namespace __format
>> // %A Locale's full weekday name.
>> chrono::weekday __wd = _S_weekday(__t);
>> if (!__wd.ok())
>> - __throw_format_error("format error: invalid weekday");
>> + {
>> + if (!_M_spec._M_debug)
>> + __throw_format_error("format error: invalid weekday");
>> +
>> + _CharT __buf[3];
>> + __out = __format::__write(std::move(__out),
>> + _S_str_d1(__buf,
>> __wd.c_encoding()));
>> + return __format::__write(std::move(__out),
>> + __string_view(_GLIBCXX_WIDEN(" is not a valid
>> weekday")));
>> + }
>>
>> locale __loc = _M_locale(__ctx);
>> const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
>> @@ -847,7 +983,17 @@ namespace __format
>> // %B Locale's full month name.
>> chrono::month __m = _S_month(__t);
>> if (!__m.ok())
>> - __throw_format_error("format error: invalid month");
>> + {
>> + if (!_M_spec._M_debug)
>> + __throw_format_error("format error: invalid month");
>> +
>> + _CharT __buf[3];
>> + __out = __format::__write(std::move(__out),
>> + _S_str_d1(__buf, (unsigned)__m));
>> + return __format::__write(std::move(__out),
>> + __string_view(_GLIBCXX_WIDEN(" is not a valid
>> month")));
>> + }
>> +
>> locale __loc = _M_locale(__ctx);
>> const auto& __tp = use_facet<__timepunct<_CharT>>(__loc);
>> const _CharT* __months[12];
>> @@ -974,7 +1120,11 @@ namespace __format
>> }
>> __out = __format::__write(std::move(__out), __sv);
>> }
>> - return std::move(__out);
>> +
>> + if (_M_spec._M_debug && __conv == 'Y' && !__y.ok()) [[unlikely]]
>> + __out = __format::__write(std::move(__out),
>> + __string_view(_GLIBCXX_WIDEN(" is not a valid
>> year")));
>> + return __out;
>> }
>>
>> template<typename _Tp, typename _FormatContext>
>> @@ -1039,7 +1189,12 @@ namespace __format
>> __buf[0] = _S_space;
>> __sv = {__buf, 2};
>> }
>> - return __format::__write(std::move(__out), __sv);
>> +
>> + __out = __format::__write(std::move(__out), __sv);
>> + if (_M_spec._M_debug && !__d.ok()) [[unlikely]]
>> + __out = __format::__write(std::move(__out),
>> + __string_view(_GLIBCXX_WIDEN(" is not a valid
>> day")));
>> + return std::move(__out);
>> }
>>
>> template<typename _Tp, typename _FormatContext>
>> @@ -1076,6 +1231,10 @@ namespace __format
>> _S_fill_two_digits(__buf + 9, __di);
>> __out = __format::__write(std::move(__out), __sv);
>> }
>> +
>> + if (_M_spec._M_debug && !__ymd.ok())
>> + __out = __format::__write(std::move(__out),
>> + __string_view(_GLIBCXX_WIDEN(" is not a valid
>> date")));
>> return std::move(__out);
>> }
>>
>> @@ -1757,6 +1916,20 @@ namespace __format
>> return weekday(_S_days(__t));
>> }
>>
>> + template<typename _Tp>
>> + static unsigned
>> + _S_weekday_index(const _Tp& __t)
>> + {
>> + using namespace ::std::chrono;
>> +
>> + if constexpr (is_same_v<_Tp, weekday_indexed>)
>> + return __t.index();
>> + else if constexpr (requires { __t.weekday_indexed(); })
>> + return __t.weekday_indexed().index();
>> + else
>> + return ((unsigned)_S_day(__t) + 6) / 7;
>> + }
>> +
>> // Remove subsecond precision from a time_point.
>> template<typename _Tp>
>> static auto
>> @@ -1851,7 +2024,7 @@ namespace __format
>> {
>> constexpr typename basic_format_parse_context<_CharT>::iterator
>> parse(basic_format_parse_context<_CharT>& __pc)
>> - { return _M_f._M_parse(__pc, __format::_Day); }
>> + { return _M_f._M_parse(__pc, __format::_Day, __defSpec); }
>>
>> template<typename _Out>
>> typename basic_format_context<_Out, _CharT>::iterator
>> @@ -1860,7 +2033,15 @@ namespace __format
>> { return _M_f._M_format(__t, __fc); }
>>
>> private:
>> - __format::__formatter_chrono<_CharT> _M_f;
>> + static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
>> + {
>> + __format::_ChronoSpec<_CharT> __res{};
>> + __res._M_debug = true;
>> + __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_d();
>> + return __res;
>> + }();
>> +
>> + __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>> };
>>
>> template<__format::__char _CharT>
>> @@ -1868,7 +2049,7 @@ namespace __format
>> {
>> constexpr typename basic_format_parse_context<_CharT>::iterator
>> parse(basic_format_parse_context<_CharT>& __pc)
>> - { return _M_f._M_parse(__pc, __format::_Month); }
>> + { return _M_f._M_parse(__pc, __format::_Month, __defSpec); }
>>
>> template<typename _Out>
>> typename basic_format_context<_Out, _CharT>::iterator
>> @@ -1877,7 +2058,17 @@ namespace __format
>> { return _M_f._M_format(__t, __fc); }
>>
>> private:
>> - __format::__formatter_chrono<_CharT> _M_f;
>> + static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
>> + {
>> + __format::_ChronoSpec<_CharT> __res{};
>> + __res._M_debug = true;
>> + __res._M_localized = true;
>> + __res._M_locale_specific = true;
>> + __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_m();
>> + return __res;
>> + }();
>> +
>> + __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>> };
>>
>> template<__format::__char _CharT>
>> @@ -1885,7 +2076,7 @@ namespace __format
>> {
>> constexpr typename basic_format_parse_context<_CharT>::iterator
>> parse(basic_format_parse_context<_CharT>& __pc)
>> - { return _M_f._M_parse(__pc, __format::_Year); }
>> + { return _M_f._M_parse(__pc, __format::_Year, __defSpec); }
>>
>> template<typename _Out>
>> typename basic_format_context<_Out, _CharT>::iterator
>> @@ -1894,7 +2085,15 @@ namespace __format
>> { return _M_f._M_format(__t, __fc); }
>>
>> private:
>> - __format::__formatter_chrono<_CharT> _M_f;
>> + static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
>> + {
>> + __format::_ChronoSpec<_CharT> __res{};
>> + __res._M_debug = true;
>> + __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_y();
>> + return __res;
>> + }();
>> +
>> + __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>> };
>>
>> template<__format::__char _CharT>
>> @@ -1902,7 +2101,7 @@ namespace __format
>> {
>> constexpr typename basic_format_parse_context<_CharT>::iterator
>> parse(basic_format_parse_context<_CharT>& __pc)
>> - { return _M_f._M_parse(__pc, __format::_Weekday); }
>> + { return _M_f._M_parse(__pc, __format::_Weekday, __defSpec); }
>>
>> template<typename _Out>
>> typename basic_format_context<_Out, _CharT>::iterator
>> @@ -1911,7 +2110,17 @@ namespace __format
>> { return _M_f._M_format(__t, __fc); }
>>
>> private:
>> - __format::__formatter_chrono<_CharT> _M_f;
>> + static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
>> + {
>> + __format::_ChronoSpec<_CharT> __res{};
>> + __res._M_debug = true;
>> + __res._M_localized = true;
>> + __res._M_locale_specific = true;
>> + __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_w();
>> + return __res;
>> + }();
>> +
>> + __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>> };
>>
>> template<__format::__char _CharT>
>> @@ -1919,7 +2128,7 @@ namespace __format
>> {
>> constexpr typename basic_format_parse_context<_CharT>::iterator
>> parse(basic_format_parse_context<_CharT>& __pc)
>> - { return _M_f._M_parse(__pc, __format::_Weekday); }
>> + { return _M_f._M_parse(__pc, __format::_Weekday, __defSpec); }
>>
>> template<typename _Out>
>> typename basic_format_context<_Out, _CharT>::iterator
>> @@ -1928,7 +2137,17 @@ namespace __format
>> { return _M_f._M_format(__t, __fc); }
>>
>> private:
>> - __format::__formatter_chrono<_CharT> _M_f;
>> + static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
>> + {
>> + __format::_ChronoSpec<_CharT> __res{};
>> + __res._M_debug = true;
>> + __res._M_localized = true;
>> + __res._M_locale_specific = true;
>> + __res._M_chrono_specs =
>> __format::_ChronoFormats<_CharT>::_S_wi();
>> + return __res;
>> + }();
>> +
>> + __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>> };
>>
>> template<__format::__char _CharT>
>> @@ -1936,7 +2155,7 @@ namespace __format
>> {
>> constexpr typename basic_format_parse_context<_CharT>::iterator
>> parse(basic_format_parse_context<_CharT>& __pc)
>> - { return _M_f._M_parse(__pc, __format::_Weekday); }
>> + { return _M_f._M_parse(__pc, __format::_Weekday, __defSpec); }
>>
>> template<typename _Out>
>> typename basic_format_context<_Out, _CharT>::iterator
>> @@ -1945,7 +2164,17 @@ namespace __format
>> { return _M_f._M_format(__t, __fc); }
>>
>> private:
>> - __format::__formatter_chrono<_CharT> _M_f;
>> + static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
>> + {
>> + __format::_ChronoSpec<_CharT> __res{};
>> + __res._M_debug = true;
>> + __res._M_localized = true;
>> + __res._M_locale_specific = true;
>> + __res._M_chrono_specs =
>> __format::_ChronoFormats<_CharT>::_S_wl();
>> + return __res;
>> + }();
>> +
>> + __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>> };
>>
>> template<__format::__char _CharT>
>> @@ -1953,7 +2182,10 @@ namespace __format
>> {
>> constexpr typename basic_format_parse_context<_CharT>::iterator
>> parse(basic_format_parse_context<_CharT>& __pc)
>> - { return _M_f._M_parse(__pc, __format::_Month|__format::_Day); }
>> + {
>> + return _M_f._M_parse(__pc, __format::_Month|__format::_Day,
>> + __defSpec);
>> + }
>>
>> template<typename _Out>
>> typename basic_format_context<_Out, _CharT>::iterator
>> @@ -1962,7 +2194,17 @@ namespace __format
>> { return _M_f._M_format(__t, __fc); }
>>
>> private:
>> - __format::__formatter_chrono<_CharT> _M_f;
>> + static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
>> + {
>> + __format::_ChronoSpec<_CharT> __res{};
>> + __res._M_debug = true;
>> + __res._M_localized = true;
>> + __res._M_locale_specific = true;
>> + __res._M_chrono_specs =
>> __format::_ChronoFormats<_CharT>::_S_md();
>> + return __res;
>> + }();
>> +
>> + __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>> };
>>
>> template<__format::__char _CharT>
>> @@ -1970,7 +2212,10 @@ namespace __format
>> {
>> constexpr typename basic_format_parse_context<_CharT>::iterator
>> parse(basic_format_parse_context<_CharT>& __pc)
>> - { return _M_f._M_parse(__pc, __format::_Month|__format::_Day); }
>> + {
>> + return _M_f._M_parse(__pc, __format::_Month|__format::_Day,
>> + __defSpec);
>> + }
>>
>> template<typename _Out>
>> typename basic_format_context<_Out, _CharT>::iterator
>> @@ -1979,7 +2224,17 @@ namespace __format
>> { return _M_f._M_format(__t, __fc); }
>>
>> private:
>> - __format::__formatter_chrono<_CharT> _M_f;
>> + static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
>> + {
>> + __format::_ChronoSpec<_CharT> __res{};
>> + __res._M_debug = true;
>> + __res._M_localized = true;
>> + __res._M_locale_specific = true;
>> + __res._M_chrono_specs =
>> __format::_ChronoFormats<_CharT>::_S_ml();
>> + return __res;
>> + }();
>> +
>> + __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>> };
>>
>> template<__format::__char _CharT>
>> @@ -1987,7 +2242,10 @@ namespace __format
>> {
>> constexpr typename basic_format_parse_context<_CharT>::iterator
>> parse(basic_format_parse_context<_CharT>& __pc)
>> - { return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday); }
>> + {
>> + return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday,
>> + __defSpec);
>> + }
>>
>> template<typename _Out>
>> typename basic_format_context<_Out, _CharT>::iterator
>> @@ -1996,7 +2254,17 @@ namespace __format
>> { return _M_f._M_format(__t, __fc); }
>>
>> private:
>> - __format::__formatter_chrono<_CharT> _M_f;
>> + static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
>> + {
>> + __format::_ChronoSpec<_CharT> __res{};
>> + __res._M_debug = true;
>> + __res._M_localized = true;
>> + __res._M_locale_specific = true;
>> + __res._M_chrono_specs =
>> __format::_ChronoFormats<_CharT>::_S_mwi();
>> + return __res;
>> + }();
>> +
>> + __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>> };
>>
>> template<__format::__char _CharT>
>> @@ -2004,7 +2272,10 @@ namespace __format
>> {
>> constexpr typename basic_format_parse_context<_CharT>::iterator
>> parse(basic_format_parse_context<_CharT>& __pc)
>> - { return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday); }
>> + {
>> + return _M_f._M_parse(__pc, __format::_Month|__format::_Weekday,
>> + __defSpec);
>> + }
>>
>> template<typename _Out>
>> typename basic_format_context<_Out, _CharT>::iterator
>> @@ -2013,7 +2284,17 @@ namespace __format
>> { return _M_f._M_format(__t, __fc); }
>>
>> private:
>> - __format::__formatter_chrono<_CharT> _M_f;
>> + static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
>> + {
>> + __format::_ChronoSpec<_CharT> __res{};
>> + __res._M_debug = true;
>> + __res._M_localized = true;
>> + __res._M_locale_specific = true;
>> + __res._M_chrono_specs =
>> __format::_ChronoFormats<_CharT>::_S_mwl();
>> + return __res;
>> + }();
>> +
>> + __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>> };
>>
>> template<__format::__char _CharT>
>> @@ -2021,7 +2302,10 @@ namespace __format
>> {
>> constexpr typename basic_format_parse_context<_CharT>::iterator
>> parse(basic_format_parse_context<_CharT>& __pc)
>> - { return _M_f._M_parse(__pc, __format::_Year|__format::_Month); }
>> + {
>> + return _M_f._M_parse(__pc, __format::_Year|__format::_Month,
>> + __defSpec);
>> + }
>>
>> template<typename _Out>
>> typename basic_format_context<_Out, _CharT>::iterator
>> @@ -2030,7 +2314,17 @@ namespace __format
>> { return _M_f._M_format(__t, __fc); }
>>
>> private:
>> - __format::__formatter_chrono<_CharT> _M_f;
>> + static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
>> + {
>> + __format::_ChronoSpec<_CharT> __res{};
>> + __res._M_debug = true;
>> + __res._M_localized = true;
>> + __res._M_locale_specific = true;
>> + __res._M_chrono_specs =
>> __format::_ChronoFormats<_CharT>::_S_ym();
>> + return __res;
>> + }();
>> +
>> + __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>> };
>>
>> template<__format::__char _CharT>
>> @@ -2038,7 +2332,7 @@ namespace __format
>> {
>> constexpr typename basic_format_parse_context<_CharT>::iterator
>> parse(basic_format_parse_context<_CharT>& __pc)
>> - { return _M_f._M_parse(__pc, __format::_Date); }
>> + { return _M_f._M_parse(__pc, __format::_Date, __defSpec); }
>>
>> template<typename _Out>
>> typename basic_format_context<_Out, _CharT>::iterator
>> @@ -2047,7 +2341,15 @@ namespace __format
>> { return _M_f._M_format(__t, __fc); }
>>
>> private:
>> - __format::__formatter_chrono<_CharT> _M_f;
>> + static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
>> + {
>> + __format::_ChronoSpec<_CharT> __res{};
>> + __res._M_debug = true;
>> + __res._M_chrono_specs = __format::_ChronoFormats<_CharT>::_S_f();
>> + return __res;
>> + }();
>> +
>> + __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>> };
>>
>> template<__format::__char _CharT>
>> @@ -2055,7 +2357,7 @@ namespace __format
>> {
>> constexpr typename basic_format_parse_context<_CharT>::iterator
>> parse(basic_format_parse_context<_CharT>& __pc)
>> - { return _M_f._M_parse(__pc, __format::_Date); }
>> + { return _M_f._M_parse(__pc, __format::_Date, __defSpec); }
>>
>> template<typename _Out>
>> typename basic_format_context<_Out, _CharT>::iterator
>> @@ -2064,7 +2366,17 @@ namespace __format
>> { return _M_f._M_format(__t, __fc); }
>>
>> private:
>> - __format::__formatter_chrono<_CharT> _M_f;
>> + static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
>> + {
>> + __format::_ChronoSpec<_CharT> __res{};
>> + __res._M_debug = true;
>> + __res._M_localized = true;
>> + __res._M_locale_specific = true;
>> + __res._M_chrono_specs =
>> __format::_ChronoFormats<_CharT>::_S_yml();
>> + return __res;
>> + }();
>> +
>> + __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>> };
>>
>> template<__format::__char _CharT>
>> @@ -2072,7 +2384,7 @@ namespace __format
>> {
>> constexpr typename basic_format_parse_context<_CharT>::iterator
>> parse(basic_format_parse_context<_CharT>& __pc)
>> - { return _M_f._M_parse(__pc, __format::_Date); }
>> + { return _M_f._M_parse(__pc, __format::_Date, __defSpec); }
>>
>> template<typename _Out>
>> typename basic_format_context<_Out, _CharT>::iterator
>> @@ -2081,7 +2393,17 @@ namespace __format
>> { return _M_f._M_format(__t, __fc); }
>>
>> private:
>> - __format::__formatter_chrono<_CharT> _M_f;
>> + static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
>> + {
>> + __format::_ChronoSpec<_CharT> __res{};
>> + __res._M_debug = true;
>> + __res._M_localized = true;
>> + __res._M_locale_specific = true;
>> + __res._M_chrono_specs =
>> __format::_ChronoFormats<_CharT>::_S_ymwi();
>> + return __res;
>> + }();
>> +
>> + __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>> };
>>
>> template<__format::__char _CharT>
>> @@ -2089,7 +2411,7 @@ namespace __format
>> {
>> constexpr typename basic_format_parse_context<_CharT>::iterator
>> parse(basic_format_parse_context<_CharT>& __pc)
>> - { return _M_f._M_parse(__pc, __format::_Date); }
>> + { return _M_f._M_parse(__pc, __format::_Date, __defSpec); }
>>
>> template<typename _Out>
>> typename basic_format_context<_Out, _CharT>::iterator
>> @@ -2098,7 +2420,17 @@ namespace __format
>> { return _M_f._M_format(__t, __fc); }
>>
>> private:
>> - __format::__formatter_chrono<_CharT> _M_f;
>> + static constexpr __format::_ChronoSpec<_CharT> __defSpec = []
>> + {
>> + __format::_ChronoSpec<_CharT> __res{};
>> + __res._M_debug = true;
>> + __res._M_localized = true;
>> + __res._M_locale_specific = true;
>> + __res._M_chrono_specs =
>> __format::_ChronoFormats<_CharT>::_S_ymwl();
>> + return __res;
>> + }();
>> +
>> + __format::__formatter_chrono<_CharT> _M_f{__defSpec};
>> };
>>
>> template<typename _Rep, typename _Period, __format::__char _CharT>
>> @@ -2947,7 +3279,7 @@ namespace __detail
>> // n.b. only decimal separator is locale dependent for specifiers
>> // used below, as sys_info uses seconds and minutes duration, the
>> // output is locale-independent.
>> - constexpr auto* __fs
>> + constexpr auto* __fs
>> = _GLIBCXX_WIDEN("[{0:%F %T},{1:%F %T},{2:%T},{3:%Q%q},{0:%Z}]");
>> local_seconds __lb(__i.begin.time_since_epoch());
>> __os << std::format(__fs, local_time_format(__lb, &__i.abbrev),
>> --
>> 2.49.0
>>
>>
More information about the Libstdc++
mailing list