<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 3749: common_iterator should handle integer-class difference types</title>
<meta property="og:title" content="Issue 3749: common_iterator should handle integer-class difference types">
<meta property="og:description" content="C++ library issue. Status: WP">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue3749.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#WP">WP</a> status.</em></p>
<h3 id="3749"><a href="lwg-defects.html#3749">3749</a>. <code>common_iterator</code> should handle integer-class difference types</h3>
<p><b>Section:</b> 24.5.5 <a href="https://wg21.link/iterators.common">[iterators.common]</a> <b>Status:</b> <a href="lwg-active.html#WP">WP</a>
 <b>Submitter:</b> Hewill Kang <b>Opened:</b> 2022-08-01 <b>Last modified:</b> 2023-11-22</p>
<p><b>Priority: </b>2
</p>
<p><b>View all issues with</b> <a href="lwg-status.html#WP">WP</a> status.</p>
<p><b>Discussion:</b></p>
<p>
The partial specialization of <code>iterator_traits</code> for <code>common_iterator</code> is defined in 
24.5.5.1 <a href="https://wg21.link/common.iterator">[common.iterator]</a> as
</p>
<pre>
template&lt;input_iterator I, class S&gt;
struct iterator_traits&lt;common_iterator&lt;I, S&gt;&gt; {
  using iterator_concept = <i>see below</i>;
  using iterator_category = <i>see below</i>;
  using value_type = iter_value_t&lt;I&gt;;
  using difference_type = iter_difference_t&lt;I&gt;;
  using pointer = <i>see below</i>;
  using reference = iter_reference_t&lt;I&gt;;
};
</pre>
<p>
where <code>difference_type</code> is defined as <code>iter_difference_t&lt;I&gt;</code> and <code>iterator_category</code> 
is defined as at least <code>input_iterator_tag</code>. However, when <code>difference_type</code> is an 
integer-class type, <code>common_iterator</code> does not satisfy <i>Cpp17InputIterator</i>, which makes 
<code>iterator_category</code> incorrectly defined as <code>input_iterator_tag</code>.
</p>
<p>
Since the main purpose of <code>common_iterator</code> is to be compatible with the legacy iterator system, 
which is reflected in its efforts to try to provide the operations required by C++17 iterators even if 
the underlying iterator does not support it. We should handle this case of difference type incompatibility 
as well.
<p/>
The proposed solution is to provide a C++17 conforming difference type by clamping the integer-class type 
to <code>ptrdiff_t</code>.
<p/>
<b>Daniel:</b>
</p>
<blockquote class="note">
<p>
The second part of this issue provides an <em>alternative</em> resolution for the first part of 
LWG <a href="lwg-active.html#3748" title="common_iterator and counted_iterator' operator- are missing cast to return type (Status: New)">3748</a><sup><a href="https://cplusplus.github.io/LWG/issue3748" title="Latest snapshot">(i)</a></sup> and solves the casting problem mentioned in LWG <a href="lwg-active.html#3748" title="common_iterator and counted_iterator' operator- are missing cast to return type (Status: New)">3748</a><sup><a href="https://cplusplus.github.io/LWG/issue3748" title="Latest snapshot">(i)</a></sup> as well.
</p>
</blockquote>

<p><i>[2022-08-23; Reflector poll]</i></p>

<p>
Set priority to 2 after reflector poll.
</p>
<p>
"I think <code>common_iterator</code> should <em>reject</em> iterators with
integer-class difference types since it can't possibly achieve the design intent
of adapting them to <i>Cpp17Iterator</i>s."
</p>
<p>
"I'm not yet convinced that we need to outright reject such uses,
but I'm pretty sure that we shouldn't mess with the difference type
and that the PR is in the wrong direction."
</p>

<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">

<p>
This wording is relative to <a href="https://wg21.link/N4910" title=" Working Draft, Standard for Programming Language C++">N4910</a>.
</p>

<ol>
<li><p>Modify 24.5.5.1 <a href="https://wg21.link/common.iterator">[common.iterator]</a> as indicated:</p>

<blockquote class="note">
<p>
[<i>Drafting note:</i> <code>common_iterator</code> requires iterator type <code>I</code> must model 
<code>input_or_output_iterator</code> which ensures that <code>iter_difference_t&lt;I&gt;</code> 
is a signed-integer-like type. The modification of <code>common_iterator::operator-</code> is to ensure 
that the pair of <code>common_iterator&lt;I, S&gt;</code> models <code>sized_sentinel_for</code> when 
<code>sized_sentinel_for&lt;I, S&gt;</code> is modeled for iterator type <code>I</code> with an 
integer-class difference type and its sentinel type <code>S</code>.]
</p>
</blockquote>

<blockquote>
<pre>
namespace std {
  <ins>template&lt;class D&gt;
    requires <i>is-signed-integer-like</i>&lt;D&gt;
  using <i>make-cpp17-diff-t</i> = conditional_t&lt;signed_integral&lt;D&gt;, D, ptrdiff_t&gt;;  <i>// exposition only</i></ins>

  template&lt;input_or_output_iterator I, sentinel_for&lt;I&gt; S>
    requires (!same_as&lt;I, S&gt; &amp;&amp; copyable&lt;I&gt;)
  class common_iterator {
  public:
    [&hellip;]
    template&lt;sized_sentinel_for&lt;I&gt; I2, sized_sentinel_for&lt;I&gt; S2>
      requires sized_sentinel_for&lt;S, I2&gt;
    friend constexpr <ins><i>make-cpp17-diff-t</i>&lt;</ins>iter_difference_t&lt;I2&gt;<ins>&gt;</ins> operator-(
      const common_iterator&amp; x, const common_iterator&lt;I2, S2&gt;&amp; y);
    [&hellip;]
  };
  
  template&lt;class I, class S&gt;
  struct incrementable_traits&lt;common_iterator&lt;I, S&gt;&gt; {
    using difference_type = <ins><i>make-cpp17-diff-t</i>&lt;</ins>iter_difference_t&lt;I&gt;<ins>&gt;</ins>;
  };

  template&lt;input_iterator I, class S&gt;
  struct iterator_traits&lt;common_iterator&lt;I, S&gt;&gt; {
    using iterator_concept = <i>see below</i>;
    using iterator_category = <i>see below</i>;
    using value_type = iter_value_t&lt;I&gt;;
    using difference_type = <ins><i>make-cpp17-diff-t</i>&lt;</ins>iter_difference_t&lt;I&gt;<ins>&gt;</ins>;
    using pointer = <i>see below</i>;
    using reference = iter_reference_t&lt;I&gt;;
  };
}
</pre>
</blockquote>
</li>

<li><p>Modify 24.5.5.6 <a href="https://wg21.link/common.iter.cmp">[common.iter.cmp]</a> as indicated:</p>

<blockquote class="note">
<p>
[<i>Drafting note:</i> If this issue is voted in at the same time as LWG <a href="lwg-active.html#3748" title="common_iterator and counted_iterator' operator- are missing cast to return type (Status: New)">3748</a><sup><a href="https://cplusplus.github.io/LWG/issue3748" title="Latest snapshot">(i)</a></sup>, the editor
is kindly informed that the changes indicated below supersede those of the before mentioned issues first 
part.]
</p>
</blockquote>

<blockquote>
<pre>
template&lt;sized_sentinel_for&lt;I&gt; I2, sized_sentinel_for&lt;I&gt; S2>
  requires sized_sentinel_for&lt;S, I2&gt;
friend constexpr <ins><i>make-cpp17-diff-t</i>&lt;</ins>iter_difference_t&lt;I2&gt;<ins>&gt;</ins> operator-(
  const common_iterator&amp; x, const common_iterator&lt;I2, S2&gt;&amp; y);
</pre>
<blockquote>
<p>
-5- <i>Preconditions</i>: <code>x.v_.valueless_by_exception()</code> and <code>y.v_.valueless_by_exception()</code> are 
each <code>false</code>.
<p/>
-6- <i>Returns</i>: <code>0</code> if <code><i>i</i></code> and <code><i>j</i></code> are each <code>1</code>, and 
otherwise <ins><code>static_cast&lt;<i>make-cpp17-diff-t</i>&lt;iter_difference_t&lt;I2&gt;&gt;&gt;(</code></ins><code>get&lt;<i>i</i>&gt;(x.v_) 
- get&lt;<i>j</i>&gt;(y.v_)</code><ins><code>)</code></ins>, where <code><i>i</i></code> is <code>x.v_.index()</code> 
and <code><i>j</i></code> is <code>y.v_.index()</code>.
</p>
</blockquote>
</blockquote>
</li>

</ol>
</blockquote>

<p><i>[2023-06-13; Varna; Tomasz provides wording]</i></p>

<p><i>[2023-06-14 Varna; Move to Ready]</i></p>

<p><i>[2023-11-11 Approved at November 2023 meeting in Kona. Status changed: Voting &rarr; WP.]</i></p>



<p id="res-3749"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4950" title=" Working Draft, Standard for Programming Language C++">N4950</a>.
</p>

<ol>
<li><p>Modify 24.5.5.1 <a href="https://wg21.link/common.iterator">[common.iterator]</a> as indicated:</p>

<blockquote>
<pre>
namespace std {
  [&hellip;]

  template&lt;input_iterator I, class S&gt;
  struct iterator_traits&lt;common_iterator&lt;I, S&gt;&gt; {
    using iterator_concept = <i>see below</i>;
    using iterator_category = <i>see below</i>; <ins>// <i>not always present</i></ins>
    using value_type = iter_value_t&lt;I&gt;;
    using difference_type = iter_difference_t&lt;I&gt;;
    using pointer = <i>see below</i>;
    using reference = iter_reference_t&lt;I&gt;;
  };
}
</pre>
</blockquote>
</li>

<li><p>Modify 24.5.5.2 <a href="https://wg21.link/common.iter.types">[common.iter.types]</a> as indicated:</p>

<blockquote>
<p>
<ins>-?- The nested <i>typedef-name</i> <code>iterator_category</code> of the specialization of <code>iterator_traits</code> for 
<code>common_iterator&lt;I, S&gt;</code> is defined if and only if <code>iter_difference_t&lt;I&gt;</code> is an integral type. 
In that case, <code>iterator_category</code> denotes <code>forward_iterator_tag</code> if the <i>qualified-id</i> 
<code>iterator_traits&lt;I&gt;::iterator_category</code> is valid and denotes a type that models 
<code>derived_from&lt;forward_iterator_tag&gt;</code>; otherwise it denotes <code>input_iterator_tag</code>.</ins>
</p>
<p>
-1- The <ins>remaining</ins> nested <i>typedef-name</i>s of the specialization of <code>iterator_traits</code> 
for <code>common_iterator&lt;I, S&gt;</code> are defined as follows<del>.</del><ins>:</ins>
</p>
<ol style="list-style-type: none">
<li><p>(1.1) &mdash; <code>iterator_concept</code> denotes <code>forward_iterator_tag</code> if <code>I</code> models 
<code>forward_iterator</code>; otherwise it denotes <code>input_iterator_tag</code>.</p></li>
<li><p><del>(1.2) &mdash; <code>iterator_category</code> denotes 
<code>forward_iterator_tag</code> if the <i>qualified-id</i> <code>iterator_traits&lt;I&gt;::iterator_category</code> is valid 
and denotes a type that models <code>derived_from&lt;forward_iterator_tag&gt;</code>; otherwise it denotes <code>input_iterator_tag</code>.</del></p></li>
<li><p>(1.3) &mdash; Let <code>a</code> denote an lvalue of type <code>const common_iterator&lt;I, S&gt;</code>. 
If the expression <code>a.operator-&gt;()</code> is well-formed, then <code>pointer</code> denotes <code>decltype(a.operator->())</code>. 
Otherwise, <code>pointer</code> denotes <code>void</code>.</p></li>
</ol>
</blockquote>
</li>

</ol>





</body>
</html>
