On Wed, 3 Apr 2024 at 10:45, Federico Kircheis via Std-Proposals <std-proposals@lists.isocpp.org> wrote:

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


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{}.

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.


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