C++ Logo

std-proposals

Advanced search

Re: [std-proposals] std::chrono::duration default constructor

From: Jonathan Wakely <cxx_at_[hidden]>
Date: Wed, 3 Apr 2024 11:51:01 +0100
On Wed, 3 Apr 2024 at 11:44, Jonathan Wakely <cxx_at_[hidden]> wrote:

>
>
> On Wed, 3 Apr 2024 at 10:45, Federico Kircheis via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> Hello,
>>
>>
>> I have a question about the default constructor of std::chrono::duration
>>
>> For example std::chrono::duration::seconds
>>
>> According to the standard, it has a default constructor, but the
>> standard does not specify to what value a default constructed duration
>> is set to object.
>>
>>
>> I found
>>
>>
>> https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/OcGX7Yj3meI
>>
>> that argues that having an uninitialized duration is by design, which
>> follows the question if the standard be more explicit?
>>
>> For me (and many colleagues) it was a surprise, as the presence of a
>> default constructor hinted that the type would be initialized.
>>
>
> No, it behaves like its rep type. If that's an integral type, then default
> initialization of a duration acts just like default initialization of its
> rep type: no initialization is performed.
>
> Value initialization will initialize it though, e.g. chrono::seconds{}.
>

Oh, and also, the default constructor cannot actually guarantee
initialization of a custom rep type.

struct urep {
  urep() { }
  int val;
  // ...
};

Even if the chrono::duration constructor value-init'd its rep member, a
chrono::duration<urep> would still be uninitialized.

That's why duration_values<Rep>::zero() explicitly uses Rep(0) not Rep(),
see the note in [time.traits.duration.values].

Arguably, this is a problem with the 'urep' type above, and not
chrono::duration's concern.



>
>
>> I find the rationale weak, as I would have thought not having a default
>> constructor would have made much more sense, but it is obviously to late
>> to change that.
>>
>
> For the common durations using an integral rep, default initialization
> creates an uninitialized value. But for a custom rep type, the default
> constructor could create an invalid value.
>
> e.g.
>
> struct drep {
> double val = std::numeric_limits<double>::quiet_NaN();
> // ...
> };
>
> std::chrono::duration<drep> d; // nan value
> std::chrono::duration<drep> d0 = d.zero(); // zero value
>
> I think there's a good argument for saying that the default constructor
> should have been specified to value-initialize its rep member. That would
> still allow the custom behaviour shown above to work, as the value init'd
> 'drep' type would still have a NaN value. But changing that would change
> the result of is_trivial_v<chrono::seconds> etc. (they would still be
> trivially copyable though).
>
>

Received on 2024-04-03 10:52:20