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?
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 > >> > > >> > > >> > >