<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2106: move_iterator wrapping iterators returning prvalues</title>
<meta property="og:title" content="Issue 2106: move_iterator wrapping iterators returning prvalues">
<meta property="og:description" content="C++ library issue. Status: C++17">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2106.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="2106"><a href="lwg-defects.html#2106">2106</a>. <code>move_iterator</code> wrapping iterators returning prvalues</h3>
<p><b>Section:</b> 24.5.4 <a href="https://wg21.link/move.iterators">[move.iterators]</a> <b>Status:</b> <a href="lwg-active.html#C++17">C++17</a>
 <b>Submitter:</b> Dave Abrahams <b>Opened:</b> 2011-11-30 <b>Last modified:</b> 2017-07-30</p>
<p><b>Priority: </b>3
</p>
<p><b>View all other</b> <a href="lwg-index.html#move.iterators">issues</a> in [move.iterators].</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>
Shouldn't <code>move_iterator</code> be specialized so that if the iterator it wraps
returns a prvalue when dereferenced, the <code>move_iterator</code> also returns by
value? Otherwise, it creates a dangling reference.
<p/>
Howard: I believe just changing <code>move_iterator&lt;I&gt;::reference</code> would do.
A direction might be testing on <code>is_reference&lt;iterator_traits&lt;I&gt;::reference&gt;</code>, 
or <code>is_reference&lt;decltype(*declval&lt;I&gt;())&gt;</code>.
<p/>
Daniel: I would prefer to use a consistent style among the iterator adaptors, so I
suggest to keep with the <code>iterator_traits</code> typedefs if possible. 
</p>
<blockquote><pre>
using reference = typename conditional&lt;
  is_reference&lt;typename iterator_traits&lt;Iterator&gt;::reference&gt;::value,
  value_type&amp;&amp;,
  value_type
&gt;::type;
</pre></blockquote>
<p>
We might also want to ensure that if <code>Iterator</code>'s <code>reference</code> type <em>is</em>
a reference, the referent is equal to <code>value_type</code> (after removal of <i>cv</i>-qualifiers). 
In <em>general</em> we have no such guarantee.
<p/>
Marc: In the default case where we don't return <code>value_type&amp;&amp;</code>, should we use 
<code>value_type</code> or should we keep the <code>reference</code> type of the wrapped iterator?
<p/>
Daniel: This suggestion looks appealing at first, but the problem here is that using this typedef
can make it impossible for <code>move_iterator</code> to satisfy its contract, which means returning
an rvalue of the value type (Currently it says rvalue-reference, but this must be fixed as of
this issue anyway). I think that user-code can reasonably expect that when it has constructed
an object <code>m</code> of <code>move_iterator&lt;It&gt;</code>, where <code>It</code> is a valid 
mutable iterator type, the expression
</p>
<blockquote><pre>
<span style="color:#C80000;font-weight:bold">It::value_type&amp;&amp; rv = *m;</span>
</pre></blockquote>
<p>
is well-formed.
<p/>
Let's set <code>R</code> equal to <code>iterator_traits&lt;Iterator&gt;::reference</code>
in the following. We can discuss the following situations:
</p>
<ol><li><code>R</code> is a reference type: We can only return the corresponding xvalue of <code>R</code>,
if <code>value_type</code> is reference-related to the referent type, else this is presumably no
forward iterator and we cannot say much about it, except that it must be convertible to
<code>value_type</code>, so it better should return a prvalue.</li>
<li><code>R</code> is not a reference type: In this case we can rely on a conversion to
<code>value_type</code> again, but not much more. Assume we would return <code>R</code> directly,
this might turn out to have a conversion to an lvalue-reference type of the value type (for
example). If that is the case, this would indirectly violate the contract of 
<code>move_iterator</code>.</li>
</ol>
<p>
In regard to the first scenario I suggest that implementations are simply required to
check that <code>V2 = remove_cv&lt;remove_reference&lt;R&gt;::type&gt;::type</code> is equal
to the value type <code>V1</code> as a criterion to return this reference as an xvalue, in all other
cases it should return the value type directly as prvalue.
<p/>
The additional advantage of this strategy is, that we always ensure that <code>reference</code> has 
the correct <i>cv</i>-qualification, if <code>R</code> is a real reference.
<p/>
It is possible to improve this a bit by indeed supporting reference-related types,
this would require to test <code>is_same&lt;V1, V2&gt;::value || is_base_of&lt;V1, V2&gt;::value</code> 
instead. I'm unsure whether (a) this additional effort is worth it and (b) a strict reading of
the forward iterator requirements seems not to allow to return a reference-related type (Whether 
this is a defect or not is another question).
</p>

<p><i>[2011-12-05: Marc Glisse comments and splits into two resolution alternatives]</i></p>


<p>
I guess I am looking at the speed of:
</p>
<blockquote><pre>
value_type x;
x = *m;
</pre></blockquote>
<p>
(copy construction would likely trigger copy elision and thus be neutral)

instead of the validity of:
</p>
<blockquote><pre>
value_type&amp;&amp; x = *m;
</pre></blockquote>
<p>
In this sense, Daniels earlier proposition that ignored <code>value_type</code> and just did 
<code>switch_lvalue_ref_to_rvalue_ref&lt;reference&gt;</code> was easier to understand (and it didn't 
require thinking about reference related types).
<p/>
The currently proposed resolution has been split into two alternatives.
</p>


<p><i>[2012, Kona]</i></p>

<p>
Move to Review.
</p>
<p>
Alisdair: This only applies to input iterators, so keep that in mind when thinking about this.
</p>
<p>
STL: I see what B is doing, but not A.
</p>
<p>
Howard: I agree.
</p>
<p>
Alisdair: Should we use <code>add_rvalue_reference</code>?
</p>
<p>
STL: No, we do not want reference collapsing.
</p>
<p>
STL: Re A, messing with the CV qualification scares me.
</p>
<p>
Alisdair: Agree. That would break my intent.
</p>
<p>
STL: Actually I don't think it's actually wrong, but I still don't see what it's doing.
</p>
<p>
Alisdair: A is picking the value type, B is picking the proxy type.
</p>
<p>
Howard: I like returning the proxy type.
</p>
<p>
STL: Returning a reference (B) seems right, because the requirements say "reference".
I suspect that B works correctly if you have a move iterator wrapping a move iterator
wrapping a thing.  I think that A would mess up the type in the middle.
</p>
<p>
Considerable discussion about which version is correct, checking various examples.
</p>
<p>
STL: Still think B is right. Still don't understand A. In A we are losing the proxyness.
</p>
<p>
Howard: Agree 100%. We don't want to lose the proxy. If it's const, so be it.
</p>
<p>
STL: B is also understandable by mortals.
</p>
<p>
Howard: Remove to review, keep A but move it out of the proposed resolution area
(but keep it for rational).
</p>
<p>
Alisdair: Adding an explanatory note might be a good idea, if someone wants to write one.
</p>
<p>
Walter: Concerned about losing the word "reference" in p.1.
</p>
<p>
Howard: <code>move_iterator</code> will return an xvalue or a prvalue, both of which are rvalues.
</p>

<p><i>[Proposed resolution A, rejected in preference to the currently proposed resolution (B)

<ol>
<li><p>Change 24.5.4 <a href="https://wg21.link/move.iterators">[move.iterators]</a> p1 as indicated:</p>

<blockquote><p>
Class template <code>move_iterator</code> is an iterator adaptor with the same behavior as the underlying iterator
except that its dereference operator implicitly converts the value returned by the underlying iterator's
dereference operator to an rvalue <del>reference</del><ins>of the value type</ins>. Some generic algorithms 
can be called with move iterators to replace copying with moving.
</p></blockquote>
</li>

<li><p>Change 24.5.4.2 <a href="https://wg21.link/move.iterator">[move.iterator]</a>, class template <code>move_iterator</code> synopsis, as indicated:</p>

<blockquote><pre>
namespace std {
  template &lt;class Iterator&gt;
  class move_iterator {
  public:
    typedef Iterator iterator_type;
    typedef typename iterator_traits&lt;Iterator&gt;::difference_type difference_type;
    typedef Iterator pointer;
    typedef typename iterator_traits&lt;Iterator&gt;::value_type value_type;
    typedef typename iterator_traits&lt;Iterator&gt;::iterator_category iterator_category;
    typedef <del>value_type&amp;&amp;</del><ins><i>see below</i></ins> reference;
    [&hellip;]
  };
}
</pre></blockquote>

</li>

<li><p>Immediately following the class template <code>move_iterator</code> synopsis in 
24.5.4.2 <a href="https://wg21.link/move.iterator">[move.iterator]</a> insert a new paragraph as indicated:</p>

<blockquote><p>
<ins>-?- Let <code><i>R</i></code> be <code>iterator_traits&lt;Iterator&gt;::reference</code> and
let <code><i>V</i></code> be <code>iterator_traits&lt;Iterator&gt;::value_type</code>. If 
<code>is_reference&lt;<i>R</i>&gt;::value</code> is <code>true</code> and if 
<code>remove_cv&lt;remove_reference&lt;<i>R</i>&gt;::type&gt;::type</code> is the same type as <code><i>V</i></code>, 
the template instantiation <code>move_iterator&lt;Iterator&gt;</code> shall define the nested type 
named <code>reference</code> as a synonym for <code>remove_reference&lt;<i>R</i>&gt;::type&amp;&amp;</code>, 
otherwise as a synonym for <code><i>V</i></code>.</ins>
</p></blockquote>
</li>
</ol>

]</i></p>


<p><i>[2012, Portland: Move to Tentatively Ready]</i></p>

<p>
AJM wonders if the implied trait might be useful elsewhere, and worth adding to type traits as a
transformation type trait.
</p>

<p>
Suspicion that the Range SG might find such a trait useful, but wait until there is clear additional
use of such a trait before standardizing.
</p>

<p>
Minor wording tweak to use <code>add_rvalue_reference</code> rather than manually adding the <code>&amp;&amp;</code>,
then move to Tentatively Ready.
</p>

<p><i>[2013-01-09 Howard Hinnant comments]</i></p>


<p>
I believe the P/R for LWG 2106 is incorrect (item 3).  The way it currently reads, <code>move_iterator&lt;I&gt;::reference</code> 
is <em>always</em> an lvalue reference.  I.e. if <code>R</code> is an lvalue reference type, then reference becomes 
<code>add_rvalue_reference&lt;R&gt;::type</code> which is just <code>R</code>. And if <code>R</code> is not a reference type, 
then reference becomes <code>R</code> (which is also just <code>R</code> ;-)).
</p>

<p>
I believe the correct wording is what was there previously:
</p>

<p>
-?- Let <code>R</code> be <code>iterator_traits&lt;Iterator&gt;::reference</code>. If <code>is_reference&lt;R&gt;::value</code> 
is true, the template instantiation <code>move_iterator&lt;Iterator&gt;</code> shall define the nested type named 
<code>reference</code> as a synonym for <code>remove_reference&lt;R&gt;::type&amp;&amp;</code>, otherwise as a synonym for 
<code>R</code>.
</p>

<p>
Additionally Marc Glisse points out that <code>move_iterator&lt;I&gt;::operator*()</code> should return 
<code>static_cast&lt;reference&gt;(*current)</code>, not <code>std::move(*current)</code>.
</p>

<p>
Previous resolution:
</p>
<blockquote class="note">
<p>This wording is relative to the FDIS.</p>

<ol>
<li><p>Change 24.5.4 <a href="https://wg21.link/move.iterators">[move.iterators]</a> p1 as indicated:</p>

<blockquote><p>
Class template <code>move_iterator</code> is an iterator adaptor with the same behavior as the underlying iterator
except that its dereference operator implicitly converts the value returned by the underlying iterator's
dereference operator to an rvalue <del>reference</del>. Some generic algorithms 
can be called with move iterators to replace copying with moving.
</p></blockquote>
</li>

<li><p>Change 24.5.4.2 <a href="https://wg21.link/move.iterator">[move.iterator]</a>, class template <code>move_iterator</code> synopsis, as indicated:</p>

<blockquote><pre>
namespace std {
  template &lt;class Iterator&gt;
  class move_iterator {
  public:
    typedef Iterator iterator_type;
    typedef typename iterator_traits&lt;Iterator&gt;::difference_type difference_type;
    typedef Iterator pointer;
    typedef typename iterator_traits&lt;Iterator&gt;::value_type value_type;
    typedef typename iterator_traits&lt;Iterator&gt;::iterator_category iterator_category;
    typedef <del>value_type&amp;&amp;</del><ins><i>see below</i></ins> reference;
    [&hellip;]
  };
}
</pre></blockquote>

</li>

<li><p>Immediately following the class template <code>move_iterator</code> synopsis in 
24.5.4.2 <a href="https://wg21.link/move.iterator">[move.iterator]</a> insert a new paragraph as indicated:</p>

<blockquote><p>
<ins>-?- Let <code><i>R</i></code> be <code>iterator_traits&lt;Iterator&gt;::reference</code>. If 
<code>is_reference&lt;<i>R</i>&gt;::value</code> is <code>true</code>, the template instantiation 
<code>move_iterator&lt;Iterator&gt;</code> shall define the nested type named <code>reference</code> 
as a synonym for <code>add_rvalue_reference&lt;<i>R</i>&gt;::type</code>, otherwise as a synonym
for <code><i>R</i></code>.</ins>
</p></blockquote>
</li>
</ol>
</blockquote>

<p><i>[2014-05-19, Daniel comments]</i></p>

<p>
The term <em>instantiation</em> has been changed to <em>specialization</em> in the newly added paragraph as
suggested by STL and much preferred by myself.
</p>

<p><i>[2014-05-19 Library reflector vote]</i></p>

<p>
The issue has been identified as Tentatively Ready based on five votes in favour.
</p>



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

<ol>
<li><p>Change 24.5.4 <a href="https://wg21.link/move.iterators">[move.iterators]</a> p1 as indicated:</p>

<blockquote><p>
Class template <code>move_iterator</code> is an iterator adaptor with the same behavior as the underlying iterator
except that its indirection operator implicitly converts the value returned by the underlying iterator's
indirection operator to an rvalue <del>reference</del>. Some generic algorithms 
can be called with move iterators to replace copying with moving.
</p></blockquote>
</li>

<li><p>Change 24.5.4.2 <a href="https://wg21.link/move.iterator">[move.iterator]</a>, class template <code>move_iterator</code> synopsis, as indicated:</p>

<blockquote><pre>
namespace std {
  template &lt;class Iterator&gt;
  class move_iterator {
  public:
    typedef Iterator iterator_type;
    typedef typename iterator_traits&lt;Iterator&gt;::difference_type difference_type;
    typedef Iterator pointer;
    typedef typename iterator_traits&lt;Iterator&gt;::value_type value_type;
    typedef typename iterator_traits&lt;Iterator&gt;::iterator_category iterator_category;
    typedef <del>value_type&amp;&amp;</del><ins><i>see below</i></ins> reference;
    [&hellip;]
  };
}
</pre></blockquote>

</li>

<li><p>Immediately following the class template <code>move_iterator</code> synopsis in 
24.5.4.2 <a href="https://wg21.link/move.iterator">[move.iterator]</a> insert a new paragraph as indicated:</p>

<blockquote><p>
<ins>-?- Let <code><i>R</i></code> be <code>iterator_traits&lt;Iterator&gt;::reference</code>. If 
<code>is_reference&lt;<i>R</i>&gt;::value</code> is <code>true</code>, the template specialization 
<code>move_iterator&lt;Iterator&gt;</code> shall define the nested type named <code>reference</code> 
as a synonym for <code>remove_reference&lt;<i>R</i>&gt;::type&amp;&amp;</code>, otherwise as a synonym
for <code><i>R</i></code>.</ins>
</p></blockquote>
</li>

<li><p>Edit  [move.iter.op.star] p1 as indicated:</p>
<blockquote><pre>
reference operator*() const;
</pre><blockquote>
<p>
-1- <i>Returns</i>: <code><del>std::move</del><ins>static_cast&lt;reference&gt;</ins>(*current)</code>.
</p>
</blockquote></blockquote>
</li>
</ol>






</body>
</html>
