On Thu, 17 Apr 2025 at 13:14, Tomasz Kaminski <tkami...@redhat.com> wrote: > > As the formattable concept is used for the formatting of ranges and tuples > that was shipped in v15, > I do not think there is a real need to backport this to v14. There is not > much harm in getting wrong response > before range and tuple formatter are implemented. > So maybe we should keep in on v15+ only?
That works for me, thanks. > > On Thu, Apr 17, 2025 at 2:09 PM Jonathan Wakely <jwak...@redhat.com> wrote: >> >> On Thu, 17 Apr 2025 at 07:06, Tomasz Kaminski <tkami...@redhat.com> wrote: >> > >> > >> > >> > On Fri, Mar 28, 2025 at 9:33 PM Jonathan Wakely <jwak...@redhat.com> wrote: >> >> >> >> On 28/03/25 16:31 +0100, Tomasz Kamiński wrote: >> >> >The formatters for chrono types defined the parse/format methods >> >> >as accepting unconstrained types, this in combination with lack >> >> >of constrain on _CharT lead to them falsy statisfying formattable >> >> >requirements for any type used as character. >> >> > >> >> >This patch adjust the fromatter<T, CharT>::parse signature to: >> >> > constexpr typename basic_format_parse_context<_CharT>::iterator >> >> > parse(basic_format_parse_context<_CharT>& __pc); >> >> >And formatter<T, CharT>::format to: >> >> > template<typename _Out> >> >> > typename basic_format_context<_Out, _CharT>::iterator >> >> > format(const T& __t, >> >> > basic_format_context<_Out, _CharT>& __fc) const; >> >> > >> >> >Furthermore we _CharT with __format::__char (char or wchar_t), >> >> > >> >> > PR libstdc++/119517 >> >> > >> >> >libstdc++-v3/ChangeLog: >> >> > >> >> > * include/bits/chrono_io.h (formatter): >> >> > Add __format::__char for _CharT and adjust parse and format >> >> > method signatures. >> >> > * testsuite/std/time/format/pr119517.cc: New test. >> >> >--- >> >> >Testing on x86_64-linux, std/time/format tests passed. >> >> >OK for trunk? >> >> > >> >> > libstdc++-v3/include/bits/chrono_io.h | 448 +++++++++--------- >> >> > .../testsuite/std/time/format/pr119517.cc | 44 ++ >> >> > 2 files changed, 262 insertions(+), 230 deletions(-) >> >> > create mode 100644 libstdc++-v3/testsuite/std/time/format/pr119517.cc >> >> > >> >> >diff --git a/libstdc++-v3/include/bits/chrono_io.h >> >> >b/libstdc++-v3/include/bits/chrono_io.h >> >> >index c55b651d049..3a5bc5695fb 100644 >> >> >--- a/libstdc++-v3/include/bits/chrono_io.h >> >> >+++ b/libstdc++-v3/include/bits/chrono_io.h >> >> >@@ -1785,277 +1785,272 @@ namespace __format >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::day, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_Day); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_Day); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::day& __t, _FormatContext& __fc) const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::day& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::month, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_Month); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_Month); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::month& __t, _FormatContext& __fc) const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::month& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::year, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_Year); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_Year); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::year& __t, _FormatContext& __fc) const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::year& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::weekday, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_Weekday); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_Weekday); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::weekday& __t, _FormatContext& __fc) const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::weekday& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::weekday_indexed, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_Weekday); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_Weekday); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::weekday_indexed& __t, _FormatContext& __fc) >> >> >const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::weekday_indexed& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::weekday_last, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_Weekday); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_Weekday); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::weekday_last& __t, _FormatContext& __fc) >> >> >const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::weekday_last& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::month_day, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_Month|__format::_Day); } >> >> >+ 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); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::month_day& __t, _FormatContext& __fc) const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::month_day& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::month_day_last, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_Month|__format::_Day); } >> >> >+ 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); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::month_day_last& __t, _FormatContext& __fc) >> >> >const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::month_day_last& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::month_weekday, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, >> >> >__format::_Month|__format::_Weekday); } >> >> >+ 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); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::month_weekday& __t, _FormatContext& __fc) >> >> >const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::month_weekday& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::month_weekday_last, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, >> >> >__format::_Month|__format::_Weekday); } >> >> >+ 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); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> > format(const chrono::month_weekday_last& __t, >> >> >- _FormatContext& __fc) const >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::year_month, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_Year|__format::_Month); } >> >> >+ 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); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::year_month& __t, _FormatContext& __fc) const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::year_month& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::year_month_day, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_Date); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_Date); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::year_month_day& __t, _FormatContext& __fc) >> >> >const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::year_month_day& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::year_month_day_last, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_Date); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_Date); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> > format(const chrono::year_month_day_last& __t, >> >> >- _FormatContext& __fc) const >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::year_month_weekday, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_Date); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_Date); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> > format(const chrono::year_month_weekday& __t, >> >> >- _FormatContext& __fc) const >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::year_month_weekday_last, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_Date); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_Date); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> > format(const chrono::year_month_weekday_last& __t, >> >> >- _FormatContext& __fc) const >> >> >- { return _M_f._M_format(__t, __fc); } >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> >+ { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _Rep, typename _Period, typename _CharT> >> >> >+ template<typename _Rep, typename _Period, __format::__char _CharT> >> >> > struct formatter<chrono::hh_mm_ss<chrono::duration<_Rep, _Period>>, >> >> > _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_TimeOfDay); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_TimeOfDay); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> > format(const chrono::hh_mm_ss<chrono::duration<_Rep, _Period>>& >> >> > __t, >> >> >- _FormatContext& __fc) const >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> >@@ -2063,34 +2058,34 @@ namespace __format >> >> > }; >> >> > >> >> > #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::sys_info, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_ChronoParts{}); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_ChronoParts{}); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::sys_info& __i, _FormatContext& __fc) const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::sys_info& __i, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__i, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _CharT> >> >> >+ template<__format::__char _CharT> >> >> > struct formatter<chrono::local_info, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_ChronoParts{}); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_ChronoParts{}); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::local_info& __i, _FormatContext& __fc) const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::local_info& __i, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return _M_f._M_format(__i, __fc); } >> >> > >> >> > private: >> >> >@@ -2098,25 +2093,24 @@ namespace __format >> >> > }; >> >> > #endif >> >> > >> >> >- template<typename _Duration, typename _CharT> >> >> >+ template<typename _Duration, __format::__char _CharT> >> >> > struct formatter<chrono::sys_time<_Duration>, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { >> >> >- auto __next = _M_f._M_parse(__pc, __format::_ZonedDateTime); >> >> >- if constexpr (!__stream_insertable) >> >> >- if (_M_f._M_spec._M_chrono_specs.empty()) >> >> >- __format::__invalid_chrono_spec(); // chrono-specs can't be >> >> >empty >> >> >- return __next; >> >> >- } >> >> >- >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::sys_time<_Duration>& __t, >> >> >- _FormatContext& __fc) const >> >> >- { return _M_f._M_format(__t, __fc); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { >> >> >+ auto __next = _M_f._M_parse(__pc, __format::_ZonedDateTime); >> >> >+ if constexpr (!__stream_insertable) >> >> >+ if (_M_f._M_spec._M_chrono_specs.empty()) >> >> >+ __format::__invalid_chrono_spec(); // chrono-specs can't be >> >> >empty >> >> >+ return __next; >> >> >+ } >> >> >+ >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::sys_time<_Duration>& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> >+ { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > static constexpr bool __stream_insertable >> >> >@@ -2126,19 +2120,18 @@ namespace __format >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _Duration, typename _CharT> >> >> >+ template<typename _Duration, __format::__char _CharT> >> >> > struct formatter<chrono::utc_time<_Duration>, _CharT> >> >> > : __format::__formatter_chrono<_CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::utc_time<_Duration>& __t, >> >> >- _FormatContext& __fc) const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::utc_time<_Duration>& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { >> >> > // Adjust by removing leap seconds to get equivalent sys_time. >> >> > // We can't just use clock_cast because we want to know if the >> >> > time >> >> >@@ -2161,19 +2154,18 @@ namespace __format >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _Duration, typename _CharT> >> >> >+ template<typename _Duration, __format::__char _CharT> >> >> > struct formatter<chrono::tai_time<_Duration>, _CharT> >> >> > : __format::__formatter_chrono<_CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::tai_time<_Duration>& __t, >> >> >- _FormatContext& __fc) const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::tai_time<_Duration>& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { >> >> > // Convert to __local_time_fmt with abbrev "TAI" and offset 0s. >> >> > // We use __local_time_fmt and not sys_time (as the standard >> >> > implies) >> >> >@@ -2193,19 +2185,18 @@ namespace __format >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _Duration, typename _CharT> >> >> >+ template<typename _Duration, __format::__char _CharT> >> >> > struct formatter<chrono::gps_time<_Duration>, _CharT> >> >> > : __format::__formatter_chrono<_CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::gps_time<_Duration>& __t, >> >> >- _FormatContext& __fc) const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::gps_time<_Duration>& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { >> >> > // Convert to __local_time_fmt with abbrev "GPS" and offset 0s. >> >> > // We use __local_time_fmt and not sys_time (as the standard >> >> > implies) >> >> >@@ -2225,72 +2216,69 @@ namespace __format >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _Duration, typename _CharT> >> >> >+ template<typename _Duration, __format::__char _CharT> >> >> > struct formatter<chrono::file_time<_Duration>, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::file_time<_Duration>& __t, >> >> >- _FormatContext& __ctx) const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::file_time<_Duration>& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { >> >> > using namespace chrono; >> >> >- return _M_f._M_format(chrono::clock_cast<system_clock>(__t), >> >> >__ctx); >> >> >+ return _M_f._M_format(chrono::clock_cast<system_clock>(__t), >> >> >__fc); >> >> > } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _Duration, typename _CharT> >> >> >+ template<typename _Duration, __format::__char _CharT> >> >> > struct formatter<chrono::local_time<_Duration>, _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_DateTime); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_DateTime); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::local_time<_Duration>& __t, >> >> >- _FormatContext& __ctx) const >> >> >- { return _M_f._M_format(__t, __ctx); } >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::local_time<_Duration>& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> >+ { return _M_f._M_format(__t, __fc); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> >- template<typename _Duration, typename _CharT> >> >> >+ template<typename _Duration, __format::__char _CharT> >> >> > struct formatter<chrono::__detail::__local_time_fmt<_Duration>, >> >> > _CharT> >> >> > { >> >> >- template<typename _ParseContext> >> >> >- constexpr typename _ParseContext::iterator >> >> >- parse(_ParseContext& __pc) >> >> >- { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } >> >> >+ constexpr typename basic_format_parse_context<_CharT>::iterator >> >> >+ parse(basic_format_parse_context<_CharT>& __pc) >> >> >+ { return _M_f._M_parse(__pc, __format::_ZonedDateTime); } >> >> > >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::__detail::__local_time_fmt<_Duration>& __t, >> >> >- _FormatContext& __ctx) const >> >> >- { return _M_f._M_format(__t, __ctx, /* use %Z for {} */ true); } >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::__detail::__local_time_fmt<_Duration>& __t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> >+ { return _M_f._M_format(__t, __fc, /* use %Z for {} */ true); } >> >> > >> >> > private: >> >> > __format::__formatter_chrono<_CharT> _M_f; >> >> > }; >> >> > >> >> > #if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI >> >> >- template<typename _Duration, typename _TimeZonePtr, typename _CharT> >> >> >+ template<typename _Duration, typename _TimeZonePtr, __format::__char >> >> >_CharT> >> >> > struct formatter<chrono::zoned_time<_Duration, _TimeZonePtr>, >> >> > _CharT> >> >> > : formatter<chrono::__detail::__local_time_fmt_for<_Duration>, >> >> > _CharT> >> >> > { >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::zoned_time<_Duration, _TimeZonePtr>& __tp, >> >> >- _FormatContext& __ctx) const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::zoned_time<_Duration, _TimeZonePtr>& __tp, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> >> >> For zoned_time the standard does specify the signature of this >> >> function, and it is supposed to look how I implemented it (see >> >> [time.format] p19). I don't remember, but that's probably what >> >> inspired me to do the same for all the other chrono formatters. >> >> >> >> But despite that, I agree that it should be fixed. >> >> >> >> > { >> >> > using _Ltf = chrono::__detail::__local_time_fmt_for<_Duration>; >> >> > using _Base = formatter<_Ltf, _CharT>; >> >> >@@ -2298,20 +2286,20 @@ namespace __format >> >> > const auto __lf = >> >> > chrono::local_time_format(__tp.get_local_time(), >> >> > &__info.abbrev, >> >> > &__info.offset); >> >> >- return _Base::format(__lf, __ctx); >> >> >+ return _Base::format(__lf, __fc); >> >> > } >> >> > }; >> >> > #endif >> >> > >> >> > // Partial specialization needed for %c formatting of >> >> > __utc_leap_second. >> >> >- template<typename _Duration, typename _CharT> >> >> >+ template<typename _Duration, __format::__char _CharT> >> >> > struct formatter<chrono::__detail::__utc_leap_second<_Duration>, >> >> > _CharT> >> >> > : formatter<chrono::utc_time<_Duration>, _CharT> >> >> > { >> >> >- template<typename _FormatContext> >> >> >- typename _FormatContext::iterator >> >> >- format(const chrono::__detail::__utc_leap_second<_Duration>& __t, >> >> >- _FormatContext& __fc) const >> >> >+ template<typename _Out> >> >> >+ typename basic_format_context<_Out, _CharT>::iterator >> >> >+ format(const chrono::__detail::__utc_leap_second<_Duration>& >> >> >__t, >> >> >+ basic_format_context<_Out, _CharT>& __fc) const >> >> > { return this->_M_f._M_format(__t, __fc); } >> >> > }; >> >> > >> >> >diff --git a/libstdc++-v3/testsuite/std/time/format/pr119517.cc >> >> >b/libstdc++-v3/testsuite/std/time/format/pr119517.cc >> >> >new file mode 100644 >> >> >index 00000000000..d1fc466eaab >> >> >--- /dev/null >> >> >+++ b/libstdc++-v3/testsuite/std/time/format/pr119517.cc >> >> >@@ -0,0 +1,44 @@ >> >> >+// { dg-do compile { target c++23 } } >> >> >+ >> >> >+#include <chrono> >> >> >+#include <format> >> >> >+#include <testsuite_hooks.h> >> >> >> >> You don't need testsuite_hooks.h because this is a compile-only test >> >> that doesn't use the runtime assertion VERIFY. >> >> >> >> With that change, the patch is OK for trunk, thanks. >> >> >> >> We should probably backport it to gcc-14 after a delay. >> > >> > OK to backport now? >> >> OK for 14 now. >> >> >> >> >> >> >+static_assert( std::formattable<std::chrono::weekday, char> ); >> >> >+static_assert( std::formattable<std::chrono::weekday, wchar_t> ); >> >> >+static_assert( !std::formattable<std::chrono::weekday, char16_t> ); >> >> >+ >> >> >+static_assert( std::formattable<std::chrono::sys_days, char> ); >> >> >+static_assert( std::formattable<std::chrono::sys_days, wchar_t> ); >> >> >+static_assert( !std::formattable<std::chrono::sys_days, char16_t> ); >> >> >+ >> >> >+static_assert( !std::formattable<std::chrono::seconds, int> ); >> >> >+ >> >> >+static_assert( !std::formattable<std::chrono::day, int> ); >> >> >+static_assert( !std::formattable<std::chrono::month, int> ); >> >> >+static_assert( !std::formattable<std::chrono::year, int> ); >> >> >+static_assert( !std::formattable<std::chrono::weekday, int> ); >> >> >+static_assert( !std::formattable<std::chrono::weekday_indexed, int> ); >> >> >+static_assert( !std::formattable<std::chrono::weekday_last, int> ); >> >> >+static_assert( !std::formattable<std::chrono::month_day, int> ); >> >> >+static_assert( !std::formattable<std::chrono::month_day_last, int> ); >> >> >+static_assert( !std::formattable<std::chrono::month_weekday, int> ); >> >> >+static_assert( !std::formattable<std::chrono::month_weekday_last, int> >> >> >); >> >> >+static_assert( !std::formattable<std::chrono::year_month_day, int> ); >> >> >+static_assert( !std::formattable<std::chrono::year_month_day_last, int> >> >> >); >> >> >+static_assert( !std::formattable<std::chrono::year_month_weekday, int> >> >> >); >> >> >+static_assert( !std::formattable<std::chrono::year_month_weekday_last, >> >> >int> ); >> >> >+static_assert( >> >> >!std::formattable<std::chrono::hh_mm_ss<std::chrono::seconds>, int> ); >> >> >+ >> >> >+static_assert( !std::formattable<std::chrono::sys_seconds, int> ); >> >> >+static_assert( !std::formattable<std::chrono::utc_seconds, int> ); >> >> >+static_assert( !std::formattable<std::chrono::tai_seconds, int> ); >> >> >+static_assert( !std::formattable<std::chrono::gps_seconds, int> ); >> >> >+static_assert( !std::formattable<std::chrono::local_seconds, int> ); >> >> >+static_assert( >> >> >!std::formattable<std::chrono::file_time<std::chrono::seconds>, int> ); >> >> >+#if _GLIBCXX_USE_CXX11_ABI || ! _GLIBCXX_USE_DUAL_ABI >> >> >+static_assert( !std::formattable<std::chrono::zoned_seconds, int> ); >> >> >+ >> >> >+static_assert( !std::formattable<std::chrono::sys_info, int> ); >> >> >+static_assert( !std::formattable<std::chrono::local_info, int> ); >> >> >+#endif >> >> >-- >> >> >2.48.1 >> >> > >> >> > >> >> >>