Title
Should chrono::from_stream() assign zero to duration for failure?
Status
c++23
Section
[time.duration.io]
Submitter
Matt Stephanson

Created on 2021-03-19.00:00:00 last changed 4 months ago

Messages

Date: 2021-06-07.16:58:04

Proposed resolution:

This wording is relative to N4878.

  1. Modify [time.duration.io] as indicated:

    template<class charT, class traits, class Rep, class Period, class Alloc = allocator<charT>>
      basic_istream<charT, traits>&
        from_stream(basic_istream<charT, traits>& is, const charT* fmt,
                    duration<Rep, Period>& d,
                    basic_string<charT, traits, Alloc>* abbrev = nullptr,
                    minutes* offset = nullptr);
    

    -3- Effects: Attempts to parse the input stream is into the duration d using the format flags given in the NTCTS fmt as specified in [time.parse]. If the parse parses everything specified by the parsing format flags without error, and yet none of the flags impacts a duration, d will be assigned a zero valueIf the parse fails to decode a valid duration, is.setstate(ios_base::failbit) is called and d is not modified. If %Z is used and successfully parsed, that value will be assigned to *abbrev if abbrev is non-null. If %z (or a modified variant) is used and successfully parsed, that value will be assigned to *offset if offset is non-null.

Date: 2021-06-07.00:00:00

[ 2021-06-07 Approved at June 2021 virtual plenary. Status changed: Voting → WP. ]

Date: 2021-04-15.00:00:00

[ 2021-04-20; Reflector poll ]

Set status to Tentatively Ready after eight votes in favour during reflector poll.

Date: 2021-03-19.00:00:00

The duration specialization of from_stream says in N4878 [time.duration.io]/3:

If the parse parses everything specified by the parsing format flags without error, and yet none of the flags impacts a duration, d will be assigned a zero value.

This is in contrast to the other specializations that say, for example, [time.cal.day.nonmembers]/8:

If the parse fails to decode a valid day, is.setstate(ios_base::failbit) is called and d is not modified.

The wording ("none of the flags impacts a duration" vs. "parse fails to decode a valid [meow]") and semantics ("assigned a zero value" vs. "not modified") are different, and it's not clear why that should be so. It also leaves unspecified what should be done in case of a parse failure, for example parsing "%j" from a stream containing "meow". [time.parse]/12 says that failbit should be set, but neither it nor [time.duration.io]/3 mention the duration result if parsing fails.

This has been discussed at the Microsoft STL project, where Howard Hinnant, coauthor of P0355R7 that added these functions, commented:

This looks like a bug in the standard to me, due to two errors on my part.

I believe that the standard should clearly say that if failbit is set, the parsed variable (duration, time_point, whatever) is not modified. I mistakenly believed that the definition of unformatted input function covered this behavior. But after review, I don't believe it does. Instead each extraction operator seems to say this separately.

I also at first did not have my example implementation coded to leave the duration unchanged. So that's how the wording got in in the first place. Here's the commit where I fixed my implementation: HowardHinnant/date@d53db7a. And I failed to propagate that fix into the proposal/standard.

It would be clearer and simpler for users if the from_stream specializations were consistent in wording and behavior.

Thanks to Stephan T. Lavavej, Miya Natsuhara, and Howard Hinnant for valuable investigation and discussion of this issue.

History
Date User Action Args
2023-11-22 15:47:43adminsetstatus: wp -> c++23
2021-06-07 16:58:04adminsetmessages: + msg11903
2021-06-07 16:58:04adminsetstatus: voting -> wp
2021-05-26 21:11:22adminsetstatus: ready -> voting
2021-04-20 20:39:33adminsetmessages: + msg11772
2021-04-20 20:39:33adminsetstatus: new -> ready
2021-03-20 18:54:08adminsetmessages: + msg11752
2021-03-19 00:00:00admincreate