This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++17 status.

### 2739. Issue with `time_point` non-member subtraction with an unsigned duration

Section: 27.6.6 [time.point.nonmember] Status: C++17 Submitter: Michael Winterberg Opened: 2016-06-23 Last modified: 2017-07-30

Priority: 0

View all other issues in [time.point.nonmember].

View all issues with C++17 status.

Discussion:

In N4594, 27.6.6 [time.point.nonmember], `operator-(time_point, duration)` is specified as:

>     template <class Clock, class Duration1, class Rep2, class Period2>
>       constexpr time_point<Clock, common_type_t<Duration1, duration<Rep2, Period2>>>
>       operator-(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs);

> > -3- Returns: `lhs + (-rhs)`.

When `Rep2` is an unsigned integral type, the behavior is quite different with arithmetic of the underlying integral types because of the requirement to negate the incoming duration and then add that. It also ends up producing different results than the underlying durations as well as the non-member `time_point::operator-=`.

Consider this program:

>     #include <chrono>
>     #include <iostream>
>     #include <cstdint>

>     using namespace std;
>     using namespace std::chrono;

>     int main()
>     {
>       const duration<uint32_t> unsignedSeconds{5};

>       auto someValue = system_clock::from_time_t(200);
>       cout << system_clock::to_time_t(someValue) << '\n';
>       cout << system_clock::to_time_t(someValue - unsignedSeconds) << '\n';
>       someValue -= unsignedSeconds;
>       cout << system_clock::to_time_t(someValue) << '\n';

>       std::chrono::seconds signedDur{200};
>       cout << signedDur.count() << '\n';
>       cout << (signedDur - unsignedSeconds).count() << '\n';
>       signedDur -= unsignedSeconds;
>       cout << signedDur.count() << '\n';
>     }

The goal of the program is to compare the behavior of `time_point` non-member `operator-`, `time_point` member `operator-=`, `duration` non-member `operator-`, and `duration` member `operator-=` with basically the same inputs.

libc++ produces this output, which appears mandated by the standard:

>     200
>     4294967491
>     195
>     200
>     195
>     195

On the other hand, libstdc++ produces this output, which is what I "intuitively" expect and behaves more consistently:

>     200
>     195
>     195
>     200
>     195
>     195

Given the seemingly brief coverage of durations with unsigned representations in the standard, this seems to be an oversight rather than a deliberate choice for this behavior. Additionally, there may be other "unexpected" behaviors with durations with an unsigned representation, this is just the one that I've come across.

[2016-07 Chicago]

Monday: P0 - tentatively ready

Proposed resolution:

This wording is relative to N4594.

1. Change 27.6.6 [time.point.nonmember] as indicated:

   >     template <class Clock, class Duration1, class Rep2, class Period2>
   >       constexpr time_point<Clock, common_type_t<Duration1, duration<Rep2, Period2>>>
   >       operator-(const time_point<Clock, Duration1>& lhs, const duration<Rep2, Period2>& rhs);

   > > -3- Returns: `lhs + (-rhs)``CT(lhs.time_since_epoch() - rhs)`, where `CT` is the type of the return value.