<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2739: Issue with time_point non-member subtraction with an unsigned duration</title>
<meta property="og:title" content="Issue 2739: Issue with time_point non-member subtraction with an unsigned duration">
<meta property="og:description" content="C++ library issue. Status: C++17">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2739.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#C++17">C++17</a> status.</em></p>
<h3 id="2739"><a href="lwg-defects.html#2739">2739</a>. Issue with <code>time_point</code> non-member subtraction with an unsigned duration</h3>
<p><b>Section:</b> 30.6.6 <a href="https://wg21.link/time.point.nonmember">[time.point.nonmember]</a> <b>Status:</b> <a href="lwg-active.html#C++17">C++17</a>
 <b>Submitter:</b> Michael Winterberg <b>Opened:</b> 2016-06-23 <b>Last modified:</b> 2017-07-30</p>
<p><b>Priority: </b>0
</p>
<p><b>View all other</b> <a href="lwg-index.html#time.point.nonmember">issues</a> in [time.point.nonmember].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++17">C++17</a> status.</p>
<p><b>Discussion:</b></p>
<p>
In N4594, 30.6.6 <a href="https://wg21.link/time.point.nonmember">[time.point.nonmember]</a>, <code>operator-(time_point, duration)</code> is specified as:
</p>
<blockquote>
<pre>
template &lt;class Clock, class Duration1, class Rep2, class Period2&gt;
  constexpr time_point&lt;Clock, common_type_t&lt;Duration1, duration&lt;Rep2, Period2&gt;&gt;&gt;
  operator-(const time_point&lt;Clock, Duration1&gt;&amp; lhs, const duration&lt;Rep2, Period2&gt;&amp; rhs);
</pre>
<blockquote>
<p>
-3- <i>Returns:</i> <code>lhs + (-rhs)</code>.
</p>
</blockquote>
</blockquote>
<p>
When <code>Rep2</code> 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 <code>time_point::operator-=</code>.
<p/>
Consider this program:
</p>
<blockquote>
<pre>
#include &lt;chrono&gt;
#include &lt;iostream&gt;
#include &lt;cstdint&gt;

using namespace std;
using namespace std::chrono;

int main()
{
  const duration&lt;uint32_t&gt; unsignedSeconds{5};

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

  std::chrono::seconds signedDur{200};
  cout &lt;&lt; signedDur.count() &lt;&lt; '\n';
  cout &lt;&lt; (signedDur - unsignedSeconds).count() &lt;&lt; '\n';
  signedDur -= unsignedSeconds;
  cout &lt;&lt; signedDur.count() &lt;&lt; '\n';
}
</pre>
</blockquote>
<p>
The goal of the program is to compare the behavior of <code>time_point</code> non-member <code>operator-</code>, 
<code>time_point</code> member <code>operator-=</code>, <code>duration</code> non-member <code>operator-</code>, and 
<code>duration</code> member <code>operator-=</code> with basically the same inputs.
<p/>
libc++ produces this output, which appears mandated by the standard:
</p>
<blockquote>
<pre>
200
4294967491
195
200
195
195
</pre>
</blockquote>
<p>
On the other hand, libstdc++ produces this output, which is what I "intuitively" expect and behaves more consistently:
</p>
<blockquote>
<pre>
200
195
195
200
195
195
</pre>
</blockquote>
<p>
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.
</p>
<p><i>[2016-07 Chicago]</i></p>

<p>Monday: P0 - tentatively ready</p>


<p id="res-2739"><b>Proposed resolution:</b></p>
<p>This wording is relative to N4594.</p>

<ol>
<li><p>Change 30.6.6 <a href="https://wg21.link/time.point.nonmember">[time.point.nonmember]</a> as indicated:</p>

<blockquote>
<pre>
template &lt;class Clock, class Duration1, class Rep2, class Period2&gt;
  constexpr time_point&lt;Clock, common_type_t&lt;Duration1, duration&lt;Rep2, Period2&gt;&gt;&gt;
  operator-(const time_point&lt;Clock, Duration1&gt;&amp; lhs, const duration&lt;Rep2, Period2&gt;&amp; rhs);
</pre>
<blockquote>
<p>
-3- <i>Returns:</i> <del><code>lhs + (-rhs)</code></del><ins><code><i>CT</i>(lhs.time_since_epoch() - rhs)</code>, where 
<code><i>CT</i></code> is the type of the return value</ins>.
</p>
</blockquote>
</blockquote>
</li>
</ol>






</body>
</html>
