Title
How should `duration` formatters format custom `rep` types?
Status
new
Section
[time.format]
Submitter
Jonathan Wakely

Created on 2024-07-08.00:00:00 last changed 3 months ago

Messages

Date: 2024-07-31.11:16:20

Proposed resolution:

This wording is relative to N4986.

  1. Modify [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>;
    
Date: 2024-07-15.00:00:00

[ 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.

Date: 2024-07-08.00:00:00

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.

[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.

History
Date User Action Args
2024-07-31 11:16:20adminsetmessages: + msg14277
2024-07-08 11:38:09adminsetmessages: + msg14250
2024-07-08 00:00:00admincreate