4118. How should duration formatters format custom rep types?

Section: 30.12 [time.format] Status: New Submitter: Jonathan Wakely Opened: 2024-07-08 Last modified: 2024-07-31

Priority: 3

View other active issues in [time.format].

View all other issues in [time.format].

View all issues with New status.

Discussion:

The formatter<chrono::duration<Rep, Period>, charT> partial specialization needs to be able to format the Rep type, because the %Q conversion specifier says to format the value returned by .count() which is of type Rep. This implies that the Rep type must be formattable, although the precise method of formatting it is not specified. Presumably either format("{}", d.count()) or ostrm << d.count() needs to work.

28.5.6.4 [format.formatter.spec] p2 (2.3) says:

For each charT, for each cv-unqualified arithmetic type ArithmeticT other than char, wchar_t, char8_t, char16_t, or char32_t, a specialization: template<> struct formatter<ArithmeticT, charT>;
However, nothing prevents the excluded types being used as the rep for a chrono::duration. This means you can use chrono::duration<wchar_t> and chrono::duration<char8_t> as durations, but you can't format them to char strings.

I think only the %Q conversion specifier formats the rep type directly (without converting durations to formattable types like hours or seconds), and so I don't think this problem exists for other chrono formatter specializations, because %Q can only be used for durations (that's not entirely clear, since %q and %Q are specified to format "the duration's unit suffix" and "the duration's numeric value", but presumably that means they can only be used for duration types).

Should the specialization of formatter for chrono::duration be constrained to require that the rep type can be formatted? Or should the %Q conversion specifier say that the numeric value is formatted by inserting into an ostream (which would treat wchar_t and char8_t rep types as characters, not integers)? Or should %Q say that the numeric value is converted to an integral type, which we know how to format?

This is somewhat related to issue 953, since it's unclear which operations "a class emulating an arithmetic type" needs to support.

[2024-07-31; Reflector poll]

Set priority to 3 after reflector poll.

"Don't convert to an integer type, that would be wrong for duration<long double> and could overflow for duration<BigInt>."

"%Q could format using +d.count()"

Some requests to disallow using code unit types as duration reps, e.g. duration<char>. Alternatively it just shouldn't be formattable. Alternatively, don't bother preventing dumb things.

There's a similar issue in operator<< for duration, which writes d.count() to the stream. For a custom rep type that might be ill-formed. For character types it might print as a character not an integer.

Proposed resolution:

This wording is relative to N4986.

  1. Modify 30.2 [time.syn] as indicated:

    
    namespace std {
      template<class Rep, class Period, class charT>
        requires formattable<Rep, charT>
        struct formatter<chrono::duration<Rep, Period>, charT>;
      template<class Duration, class charT>
        struct formatter<chrono::sys_time<Duration>, charT>;