<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta charset="utf-8">
<title>C++ Standard Library Issues to be moved in Virtual Plenary, Feb. 2021</title>
<style type="text/css">
  p {text-align:justify}
  li {text-align:justify}
  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 {border-collapse: collapse;}
</style>
</head>
<body>
<h1>C++ Standard Library Issues to be moved in Virtual Plenary, Feb. 2021</h1>
<table>
<tr>
<td align="left">Doc. no.</td>
<td align="left">P2315R0</td>
</tr>
<tr>
<td align="left">Date:</td>
<td align="left"><p>2021-02-12</p>
</td>
</tr>
<tr>
<td align="left">Audience:</td>
<td align="left">WG21</td>
</tr>
<tr>
<td align="left">Reply to:</td>
<td align="left">Jonathan Wakely &lt;<a href="mailto:lwgchair@gmail.com">lwgchair@gmail.com</a>&gt;</td>
</tr>
</table>
<h2 id="tentatively_ready">Tentatively Ready Issues</h2>
<hr>
<h3><a name="3391" href="https://cplusplus.github.io/LWG/lwg-active.html#3391">3391</a>. Problems with <tt>counted_iterator/move_iterator::base() const &amp;</tt></h3>
<p><b>Section:</b> 23.5.3 <a href="https://wg21.link/move.iterators">[move.iterators]</a>, 23.5.6 <a href="https://wg21.link/iterators.counted">[iterators.counted]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Patrick Palka <b>Opened:</b> 2020-02-07 <b>Last modified:</b> 2020-02-10</p>
<p><b>Priority: </b>2
</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#move.iterators">issues</a> in [move.iterators].</p>
<p><b>Discussion:</b></p>
<p>
It is not possible to use the <tt>const &amp;</tt> overloads of <tt>counted_iterator::base()</tt> or
<tt>move_iterator::base()</tt> to get at an underlying move-only iterator in order to compare it 
against a sentinel.
<p/>
More concretely, assuming issue LWG <a href="https://cplusplus.github.io/LWG/lwg-defects.html#3389">3389</a> is fixed, this means that
</p>
<blockquote><pre>
auto v = r | views::take(5);
ranges::begin(v) == ranges::end(v);
</pre></blockquote>
<p>
is invalid when <tt>r</tt> is a <tt>view</tt> whose <tt>begin()</tt> is a move-only input iterator.
The code is invalid because <tt>ranges::take_view::sentinel::operator==()</tt> must call 
<tt>counted_iterator::base()</tt> to compare the underlying iterator against its sentinel, and 
therefore this <tt>operator==()</tt> requires that the underlying iterator is <tt>copy_constructible</tt>.
<p/>
Suggested resolution:
<p/>
Make these <tt>const &amp; base()</tt> overloads return the underlying iterator by <tt>const</tt> reference.  
Remove the <tt>copy_constructible</tt> constraint on these overloads. Perhaps the <tt>base()</tt> 
overloads for the iterator wrappers in 24.7 <a href="https://wg21.link/range.adaptors">[range.adaptors]</a> could use the same treatment?
</p>

<p><i>[2020-02 Prioritized as P2 Monday morning in Prague]</i></p>


<p><i>[2021-01-28; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after five votes in favour during reflector poll.
</p>



<p><b>Proposed resolution:</b></p>
<p>This wording is relative to <a href="https://wg21.link/n4849">N4849</a>.</p>

<ol>
<li><p>Modify 23.5.3.2 <a href="https://wg21.link/move.iterator">[move.iterator]</a>, class template <tt>move_iterator</tt> synopsis, as indicated:</p>

<blockquote>
<pre>
namespace std {
  template&lt;class Iterator&gt;
  class move_iterator {
  public:
    using iterator_type = Iterator;
    [&hellip;]
    constexpr <ins>const</ins> iterator_type<ins>&amp;</ins> base() const &amp;;
    constexpr iterator_type base() &amp;&amp;;
    [&hellip;]
  };
}
</pre>
</blockquote>
</li>

<li><p>Modify 23.5.3.5 <a href="https://wg21.link/move.iter.op.conv">[move.iter.op.conv]</a> as indicated:</p>

<blockquote>
<pre>
constexpr <ins>const</ins> Iterator<ins>&amp;</ins> base() const &amp;;
</pre>
<blockquote>
<p>
<del>-1- <i>Constraints:</i> <tt>Iterator</tt> satisfies <tt>copy_constructible</tt>.</del>
<p/>
<del>-2- <i>Preconditions:</i> <tt>Iterator</tt> models <tt>copy_constructible</tt>.</del>
<p/>
-3- <i>Returns:</i> <tt>current</tt>.
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 23.5.6.1 <a href="https://wg21.link/counted.iterator">[counted.iterator]</a>, class template <tt>counted_iterator</tt> synopsis, as indicated:</p>

<blockquote>
<pre>
namespace std {
  template&lt;input_or_output_iterator I&gt;
  class counted_iterator {
  public:
    using iterator_type = I;
    [&hellip;]
    constexpr <ins>const</ins> I<ins>&amp;</ins> base() const &amp; <del>requires copy_constructible&lt;I&gt;</del>;
    constexpr I base() &amp;&amp;;
    [&hellip;]
  };
}
</pre>
</blockquote>
</li>

<li><p>Modify 23.5.6.3 <a href="https://wg21.link/counted.iter.access">[counted.iter.access]</a> as indicated:</p>

<blockquote>
<pre>
constexpr <ins>const</ins> I<ins>&amp;</ins> base() const &amp; <del>requires copy_constructible&lt;I&gt;</del>;
</pre>
<blockquote>
<p>
-1- <i>Effects:</i> Equivalent to: <tt>return current;</tt>
</p>
</blockquote>
</blockquote>
</li>
</ol>





<hr>
<h3><a name="3433" href="https://cplusplus.github.io/LWG/lwg-active.html#3433">3433</a>. <tt>subrange::advance(n)</tt> has UB when <tt>n &lt; 0</tt></h3>
<p><b>Section:</b> 24.5.4.3 <a href="https://wg21.link/range.subrange.access">[range.subrange.access]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Casey Carter <b>Opened:</b> 2020-04-21 <b>Last modified:</b> 2020-09-06</p>
<p><b>Priority: </b>2
</p>
<p><b>Discussion:</b></p>
<p>
<tt>subrange::advance(n)</tt> is specified to call <tt>ranges::advance(<i>begin_</i>, n, <i>end_</i>)</tt> 
in both <tt><i>StoreSize</i></tt> and <tt>!<i>StoreSize</i></tt> cases (24.5.4.3 <a href="https://wg21.link/range.subrange.access">[range.subrange.access]</a>/9). 
Unfortunately, <tt>ranges::advance(<i>begin_</i>, n, <i>end_</i>)</tt> has undefined behavior when 
<tt>n &lt; 0</tt> unless <tt>[<i>end_</i>, <i>begin_</i>)</tt> denotes a valid range 
(23.4.4.2 <a href="https://wg21.link/range.iter.op.advance">[range.iter.op.advance]</a>/5). This would all be perfectly fine &mdash; the UB is exposed to 
the caller via effects-equivalent-to &mdash; were it not the design intent that <tt>subrange::advance(-n)</tt> 
be usable to reverse the effects of <tt>subrange::advance(n)</tt> when the <tt>subrange</tt> has a 
bidirectional iterator type. That is, however, clearly the design intent: <tt>subrange::prev()</tt>, 
for example, is equivalent to <tt>subrange::advance(-1)</tt>.
</p>

<p><i>[2020-05-11; Reflector prioritization]</i></p>

<p>
Set priority to 2 after reflector discussions.
</p>

<p><i>[2021-01-15; Issue processing telecon]</i></p>

<p>
Set status to Tentatively Ready after discussion and poll.
<table>
<tr><th>F</th><th>A</th><th>N</th></tr>
<tr><td>7</td><td>0</td><td>3</td></tr>
</table>
</p>


<p><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/n4861">N4861</a>.
</p>

<ol>
<li><p>Modify 24.5.4.3 <a href="https://wg21.link/range.subrange.access">[range.subrange.access]</a> as indicated:</p>

<blockquote>
<pre>
constexpr subrange&amp; advance(iter_difference_t&lt;I&gt; n);
</pre>
<blockquote>
<p>
-9- <i>Effects:</i> Equivalent to:
<ol style="list-style-type: none">
<li><p><del>(9.1) &mdash; If <tt><i>StoreSize</i></tt> is <tt>true</tt>,</del></p>
<blockquote><pre>
<del>auto d = n - ranges::advance(<i>begin_</i>, n, <i>end_</i>);
if (d &gt;= 0)
  <i>size_</i> -= <i>to-unsigned-like</i>(d);
else
  <i>size_</i> += <i>to-unsigned-like</i>(-d);
return *this;</del>
</pre></blockquote>
</li>
<li><p><del>(9.2) &mdash; Otherwise,</del></p>
<blockquote><pre>
<del>ranges::advance(<i>begin_</i>, n, <i>end_</i>);
return *this;</del>
</pre></blockquote>
</li>
</ol>
<blockquote><pre>
<ins>if constexpr (bidirectional_iterator&lt;I&gt;) {
  if (n &lt; 0) {
    ranges::advance(<i>begin_</i>, n);
    if constexpr (<i>StoreSize</i>)
      <i>size_</i> += <i>to-unsigned-like</i>(-n);
    return *this;
  }
}

auto d = n - ranges::advance(<i>begin_</i>, n, <i>end_</i>);
if constexpr (<i>StoreSize</i>)
  <i>size_</i> -= <i>to-unsigned-like</i>(d);
return *this;</ins>
</pre></blockquote>
</p>
</blockquote>
</blockquote>
</li>
</ol>




<hr>
<h3><a name="3490" href="https://cplusplus.github.io/LWG/lwg-active.html#3490">3490</a>. <tt>ranges::drop_while_view::begin()</tt> is missing a precondition</h3>
<p><b>Section:</b> 24.7.10.2 <a href="https://wg21.link/range.drop.while.view">[range.drop.while.view]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Michael Schellenberger Costa <b>Opened:</b> 2020-10-13 <b>Last modified:</b> 2020-11-07</p>
<p><b>Priority: </b>0
</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#range.drop.while.view">issues</a> in [range.drop.while.view].</p>
<p><b>Discussion:</b></p>
<p>
Similar to <tt>ranges::filter_view</tt> 24.7.5.2 <a href="https://wg21.link/range.filter.view">[range.filter.view]</a> p3, <tt>ranges::drop_while_view</tt> 
should have a precondition on its <tt>begin()</tt> method that the predicate is set.
<p/>
I propose to add as 24.7.10.2 <a href="https://wg21.link/range.drop.while.view">[range.drop.while.view]</a> p3:
</p>
<blockquote><pre>
<ins><i>Preconditions:</i> <tt><i>pred_</i>.has_value()</tt>.</ins>  
</pre></blockquote>


<p><i>[2020-11-07; Reflector prioritization]</i></p>

<p>
Set priority to 0 and status to Tentatively Ready after six votes in favour during reflector discussions.
</p>


<p><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/n4868">N4868</a>. 
</p>

<ol>
<li>
<p>
Modify 24.7.10.2 <a href="https://wg21.link/range.drop.while.view">[range.drop.while.view]</a> as indicated:
</p>

<blockquote class="note">
<p>
Since we usually don't rely on implicit <tt>bool</tt> conversion in <i>Preconditions:</i> elements 
an explicit "is <tt>true</tt>" has been added. Editorial fixes of the referenced paragraph
24.7.10.2 <a href="https://wg21.link/range.drop.while.view">[range.drop.while.view]</a> p3 and similar places have been requested separately.
</p>
</blockquote>

<blockquote>
<pre>
constexpr auto begin();
</pre>
<blockquote>
<p>
<ins>-?- <i>Preconditions:</i> <tt><i>pred_</i>.has_value()</tt> is <tt>true</tt>.</ins>
<p/>
-3- <i>Returns:</i> <tt>ranges::find_if_not(<i>base_</i>, cref(*<i>pred_</i>))</tt>.
<p/>
-4- [&hellip;]
</p>
</blockquote>
</blockquote>
</li>
</ol>





<hr>
<h3><a name="3492" href="https://cplusplus.github.io/LWG/lwg-active.html#3492">3492</a>. Minimal improvements to <tt>elements_view::<i>iterator</i></tt></h3>
<p><b>Section:</b> 24.7.16.3 <a href="https://wg21.link/range.elements.iterator">[range.elements.iterator]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Michael Schellenberger Costa <b>Opened:</b> 2020-10-28 <b>Last modified:</b> 2020-11-15</p>
<p><b>Priority: </b>0
</p>
<p><b>View other</b> <a href="https://cplusplus.github.io/LWG/lwg-index-open.html#range.elements.iterator">active issues</a> in [range.elements.iterator].</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#range.elements.iterator">issues</a> in [range.elements.iterator].</p>
<p><b>Discussion:</b></p>
<p>
During code review of <tt>elements_view</tt> for MSVC-STL we found two issues that should be easily addressed:
</p>
<ol>
<li>
<p><tt>elements_view::<i>iterator</i></tt> constraints both <tt>operator++(int)</tt> member functions</p>
<blockquote><pre>
constexpr void operator++(int) requires (!forward_range&lt;<i>Base</i>&gt;);
constexpr <i>iterator</i> operator++(int) requires forward_range&lt;<i>Base</i>&gt;;  
</pre></blockquote>
<p>
However, given that a constrained method would be preferred we only need to constrain one of those. 
The proposal would be to remove the constraint from the <tt>void</tt> returning overload and change 
the declaration to
</p>
<blockquote><pre>
constexpr void operator++(int);
constexpr <i>iterator</i> operator++(int) requires forward_range&lt;<i>Base</i>&gt;;  
</pre></blockquote>
</li>
<li>
<p><tt>elements_view::<i>iterator</i> operator-</tt> is constrained as follows:</p>
<blockquote><pre>
friend constexpr difference_type operator-(const <i>iterator</i>&amp; x, const <i>iterator</i>&amp; y)
  requires random_access_range&lt;<i>Base</i>&gt;; 
</pre></blockquote>
<p>
However, that requires its base to have <tt>operator-</tt> defined. We should change the constraint to 
<tt>sized_sentinel_for&lt;iterator_t&lt;<i>Base</i>&gt;, iterator_t&lt;Base&gt;&gt;</tt>:
</p>
<blockquote><pre>
friend constexpr difference_type operator-(const <i>iterator</i>&amp; x, const <i>iterator</i>&amp; y)
  requires sized_sentinel_for&lt;iterator_t&lt;<i>Base</i>&gt;, iterator_t&lt;<i>Base</i>&gt;&gt;;
</pre></blockquote>
</li>
</ol>

<p><i>[2020-11-01; Daniel comments]</i></p>

<p>
Bullet (2) of the discussion has already been resolved by LWG <a href="https://cplusplus.github.io/LWG/lwg-defects.html#3483">3483</a>, it has therefore
been omitted from the proposed wording below.
</p>

<p><i>[2020-11-15; Reflector prioritization]</i></p>

<p>
Set priority to 0 and status to Tentatively Ready after five votes in favour during reflector discussions.
</p>


<p><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/n4868">N4868</a>. 
</p>

<blockquote class="note">
<p>
This wording intentionally only touches <tt>operator++(int)</tt> and <em>not</em> <tt>operator-</tt>,
see the 2020-11-01 comment for the reason why.
</p>
</blockquote>

<ol>
<li>
<p>
Modify 24.7.16.3 <a href="https://wg21.link/range.elements.iterator">[range.elements.iterator]</a>, class template <tt>elements_view::<i>iterator</i></tt> synopsis, 
as indicated:
</p>

<blockquote>
<blockquote>
<pre>
[&hellip;]
constexpr <i>iterator</i>&amp; operator++();
constexpr void operator++(int) <del>requires (!forward_range&lt;<i>Base</i>&gt;)</del>;
constexpr <i>iterator</i> operator++(int) requires forward_range&lt;<i>Base</i>&gt;;
[&hellip;]
</pre>
</blockquote>
[&hellip;]
<pre>
constexpr void operator++(int) <del>requires (!forward_range&lt;<i>Base</i>&gt;)</del>;
</pre>
<blockquote>
<p>
-6- <i>Effects:</i> Equivalent to: <tt>++<i>current_</i></tt>.
</p>
</blockquote>
<pre>
constexpr <i>iterator</i> operator++(int) requires forward_range&lt;<i>Base</i>&gt;;
</pre>
[&hellip;]
</blockquote>
</li>
</ol>





<hr>
<h3><a name="3494" href="https://cplusplus.github.io/LWG/lwg-active.html#3494">3494</a>. Allow ranges to be conditionally borrowed</h3>
<p><b>Section:</b> 24.7.15 <a href="https://wg21.link/range.reverse">[range.reverse]</a>, 24.7.7 <a href="https://wg21.link/range.take">[range.take]</a>, 24.7.9 <a href="https://wg21.link/range.drop">[range.drop]</a>, 24.7.10 <a href="https://wg21.link/range.drop.while">[range.drop.while]</a>, 24.7.14 <a href="https://wg21.link/range.common">[range.common]</a>, 24.7.10 <a href="https://wg21.link/range.drop.while">[range.drop.while]</a>, 24.7.16 <a href="https://wg21.link/range.elements">[range.elements]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Barry Revzin <b>Opened:</b> 2020-11-01 <b>Last modified:</b> 2021-01-15</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>Discussion:</b></p>
<p>
Consider the following approach to trimming a <tt>std::string</tt>:
</p>
<blockquote><pre>
auto trim(std::string const&amp; s) {
  auto isalpha = [](unsigned char c){ return std::isalpha(c); };
  auto b = ranges::find_if(s, isalpha);
  auto e = ranges::find_if(s | views::reverse, isalpha).base();
  return subrange(b, e);
}
</pre></blockquote>
<p>
This is a fairly nice and, importantly, safe way to implement <tt>trim</tt>. The iterators <tt>b</tt> 
and <tt>e</tt> returned from <tt>find_if</tt> will not dangle, since they point into the <tt>string s</tt> 
whose lifetime outlives the function. But the status quo in C++20 is that <tt>s | views::reverse</tt> 
is not a borrowed range (because <tt>reverse_view&lt;V&gt;</tt> is never a borrowed range for any <tt>V</tt>). 
As a result, <tt>find_if(s | views::reverse, isalpha)</tt> returns <em>dangling</em> rather than 
a real iterator.
<p/>
Instead, you have to write it this way, introducing a new named variable for the reversed view:
</p>
<blockquote><pre>
auto trim(std::string const&amp; s) {
  auto isalpha = [](unsigned char c){ return std::isalpha(c); };
  auto b = ranges::find_if(s, isalpha);
  auto reversed = s | views::reverse;
  auto e = ranges::find_if(reversed, isalpha).base();
  return subrange(b, e);
}
</pre></blockquote>
<p>
But borrowed range can be a transitive property. <tt>s</tt> itself is a borrowed range (as all 
lvalue references are) so <tt>s | views::reverse</tt> could be made to be too, which would allow 
the first example above to work with really no downside. We know such an iterator would not dangle, 
we just need to teach the library this.
<p/>
<a href="https://wg21.link/p2017R1">P2017R1</a> resolves this by making <tt>reverse_view&lt;V&gt;</tt> 
a borrowed range when <tt>V</tt> is a borrowed range (and likewise several other range adapters).
</p>


<p><b>Rationale:</b></p>
Resolved by <a href="https://wg21.link/p2017R1">P2017R1</a>.


<p><i>[2021-01-15; Telecon prioritization]</i></p>

<p>
Set status to Tentatively Ready after five P0 votes in reflector discussion.
</p>

<p><b>Proposed resolution:</b></p>





<hr>
<h3><a name="3495" href="https://cplusplus.github.io/LWG/lwg-active.html#3495">3495</a>. <tt>constexpr launder</tt> makes pointers to inactive members of unions usable</h3>
<p><b>Section:</b> 17.6.5 <a href="https://wg21.link/ptr.launder">[ptr.launder]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Hubert Tong  <b>Opened:</b> 2020-11-10 <b>Last modified:</b> 2021-02-08</p>
<p><b>Priority: </b>3
</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#ptr.launder">issues</a> in [ptr.launder].</p>
<p><b>Discussion:</b></p>
<p>
The wording in 17.6.5 <a href="https://wg21.link/ptr.launder">[ptr.launder]</a> paragraph 4:
</p>
<blockquote style="border-left: 3px solid #ccc;padding-left: 15px;">
<p>
An invocation of this function may be used in a core constant expression whenever the value of 
its argument may be used in a core constant expression.
</p>
</blockquote>
<p>
can be taken to mean that the invocation may be used only when the value of its argument can be 
used in place of the invocation itself.
<p/>
That interpretation is not particularly obvious, but based on comments on the CWG reflector (see 
<a href="https://lists.isocpp.org/core/2020/11/10153.php">here</a>), that is the interpretation 
that matches the design intent.
<p/>
Consider:
</p>
<blockquote><pre>
#include &lt;new&gt;

struct A { int x; int y; };
struct B { float x; int y; };

union U {
  A a;
  B b;
};

constexpr A foo() {
  U u;
  int* byp = &amp;u.b.y;
  static_assert(&amp;u.b.y == static_cast&lt;void*&gt;(&amp;u.a.y));
  u.a.y = 42;
  *std::launder(byp) = 13;
  return u.a;
}

extern constexpr A globA = foo();
</pre></blockquote>
<p>
If the <tt>static_assert</tt> succeeds, then a possible interpretation is that the source file 
above compiles because the call to <tt>std::launder</tt> produces a pointer to <tt>u.a.y</tt>.
That interpretation is apparently not desirable.
</p>

<p><i>[2020-11-21; Reflector prioritization]</i></p>

<p>
Set priority to 3 during reflector discussions.
</p>

<p><i>[2020-12-07; Davis Herring comments]</i></p>

<p>
This issue is related to <a href="https://wg21.link/cwg2464">CWG 2464</a>.
</p>

<p><i>[2021-02-08; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after five votes in favour during reflector poll.
</p>



<p><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/n4868">N4868</a>. 
</p>

<ol>
<li>
<p>
Modify 17.6.5 <a href="https://wg21.link/ptr.launder">[ptr.launder]</a> as indicated:
</p>

<blockquote>
<pre>
template&lt;class T&gt; [[nodiscard]] constexpr T* launder(T* p) noexcept;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-4- <i>Remarks:</i> An invocation of this function may be used in a core constant expression <del>whenever 
the</del><ins>if and only if the (converted)</ins> value of its argument may be used in <del>a core 
constant expression</del><ins>place of the function invocation</ins>. A byte of storage <tt><i>b</i></tt> is 
reachable through a pointer value that points to an object <tt><i>Y</i></tt> if there is an object <tt><i>Z</i></tt>, 
pointer-interconvertible with <tt><i>Y</i></tt>, such that <tt><i>b</i></tt> is within the storage occupied 
by <tt><i>Z</i></tt>, or the immediately-enclosing array object if <tt><i>Z</i></tt> is an array element.
<p/>
[&hellip;]
</p>
</blockquote>
</blockquote>
</li>
</ol>





<hr>
<h3><a name="3500" href="https://cplusplus.github.io/LWG/lwg-active.html#3500">3500</a>. <tt>join_view::iterator::operator-&gt;()</tt> is bogus</h3>
<p><b>Section:</b> 24.7.11.3 <a href="https://wg21.link/range.join.iterator">[range.join.iterator]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Michael Schellenberger Costa <b>Opened:</b> 2020-11-15 <b>Last modified:</b> 2020-11-21</p>
<p><b>Priority: </b>0
</p>
<p><b>View other</b> <a href="https://cplusplus.github.io/LWG/lwg-index-open.html#range.join.iterator">active issues</a> in [range.join.iterator].</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#range.join.iterator">issues</a> in [range.join.iterator].</p>
<p><b>Discussion:</b></p>
<p>
There seems to be a copy &amp; paste error in the <tt>join_view::iterator::operator-&gt;()</tt> 
specification. According to 24.7.11.3 <a href="https://wg21.link/range.join.iterator">[range.join.iterator]</a> p8 it is specified as:
</p>
<blockquote>
<pre>
constexpr iterator_t&lt;<i>Base</i>&gt; operator-&gt;() const
  requires <i>has-arrow</i>&lt;iterator_t&lt;Base&gt;&gt; &amp;&amp; copyable&lt;iterator_t&lt;Base&gt;&gt;;
</pre>
<blockquote>
<p>
-8- <i>Effects:</i> Equivalent to <tt>return <i>inner_</i>;</tt>
</p>
</blockquote>
</blockquote>
<p>
Now <tt><i>inner_</i></tt> is of type <tt>iterator_t&lt;range_reference_t&lt;Base&gt;&gt;</tt>. So it 
is unclear how that should be converted to <tt>iterator_t&lt;<i>Base</i>&gt;</tt>, or why the 
constraints concern the outer iterator type <tt>iterator_t&lt;<i>Base</i>&gt;</tt>. On the other hand 
returning <tt><i>outer_</i></tt> would not make any sense here.
<p/>
As far as I can tell we should replace <tt>iterator_t&lt;<i>Base</i>&gt;</tt> with 
<tt>iterator_t&lt;range_reference_t&lt;<i>Base</i>&gt;&gt;</tt> so that the new specification would 
read
</p>
<blockquote>
<pre>
constexpr iterator_t&lt;range_reference_t&lt;<i>Base</i>&gt;&gt; operator-&gt;() const
 requires <i>has-arrow</i>&lt;iterator_t&lt;range_reference_t&lt;<i>Base</i>&gt;&gt;&gt; 
   &amp;&amp; copyable&lt;iterator_t&lt;range_reference_t&lt;<i>Base</i>&gt;&gt;&gt;;
</pre>
<blockquote>
<p>
-8- <i>Effects:</i> Equivalent to <tt>return <i>inner_</i>;</tt>
</p>
</blockquote>
</blockquote>
<p>
Generally it would help readability of the specification a lot if we would introduce some exposition only aliases:
</p>
<blockquote>
<pre>
using OuterIter = iterator_t&lt;<i>Base</i>&gt;; <i>//exposition-only</i>
using InnerIter = iterator_t&lt;range_reference_t&lt;<i>Base</i>&gt;&gt; <i>//exposition-only</i>
</pre>
</blockquote>
<p>
and use them throughout <tt>join_view::<i>iterator</i></tt>.
</p>

<p><i>[2020-11-21; Reflector prioritization]</i></p>

<p>
Set priority to 0 and status to Tentatively Ready after six votes in favour during reflector discussions.
</p>


<p><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/n4868">N4868</a>. 
</p>

<ol>
<li>
<p>
Modify 24.7.11.3 <a href="https://wg21.link/range.join.iterator">[range.join.iterator]</a>, class template <tt>join_view::<i>iterator</i></tt> synopsis, 
as indicated:
</p>

<blockquote>
<blockquote>
<pre>
template&lt;input_range V&gt;
  requires view&lt;V&gt; &amp;&amp; input_range&lt;range_reference_t&lt;V&gt;&gt; &amp;&amp;
           (is_reference_v&lt;range_reference_t&lt;V&gt;&gt; ||
            view&lt;range_value_t&lt;V&gt;&gt;)
struct join_view&lt;V&gt;::<i>iterator</i> {
private:
  using <i>Parent</i> = <i>// exposition only</i>
    conditional_t&lt;Const, const join_view, join_view&gt;;
  using Base = conditional_t&lt;Const, const V, V&gt;; <i>// exposition only</i>
  <ins>using <i>OuterIter</i> = iterator_t&lt;<i>Base</i>&gt;; <i>//exposition-only</i>
  using <i>InnerIter</i> = iterator_t&lt;range_reference_t&lt;<i>Base</i>&gt;&gt; <i>//exposition-only</i></ins>
  static constexpr bool <i>ref-is-glvalue</i> = <i>// exposition only</i>
    is_reference_v&lt;range_reference_t&lt;<i>Base</i>&gt;&gt;;
  <ins><i>OuterIter</i></ins><del>iterator_t&lt;<i>Base</i>&gt;</del> <i>outer_</i> = <ins><i>OuterIter</i></ins><del>iterator_t&lt;<i>Base</i>&gt;</del>(); <i>// exposition only</i>
  <ins><i>InnerIter</i></ins><del>iterator_t&lt;range_reference_t&lt;<i>Base</i>&gt;&gt;</del> <i>inner_</i> = <i>// exposition only</i>
    <ins><i>InnerIter</i></ins><del>iterator_t&lt;range_reference_t&lt;<i>Base</i>&gt;&gt;</del>();
  <i>Parent</i>* <i>parent_</i> = nullptr; <i>// exposition only</i>
  constexpr void <i>satisfy</i>(); <i>// exposition only</i>
public:
  [&hellip;]
  <i>iterator</i>() = default;
  constexpr <i>iterator</i>(<i>Parent</i>&amp; parent, <ins><i>OuterIter</i></ins><del>iterator_t&lt;<i>Base</i>&gt;</del> outer);
  constexpr <i>iterator</i>(<i>iterator</i>&lt;!Const&gt; i)
    requires Const &amp;&amp;
             convertible_to&lt;iterator_t&lt;V&gt;, <ins><i>OuterIter</i></ins><del>iterator_t&lt;<i>Base</i>&gt;</del>&gt; &amp;&amp;
             convertible_to&lt;iterator_t&lt;<i>InnerRng</i>&gt;,
                            <ins><i>InnerIter</i></ins><del>iterator_t&lt;range_reference_t&lt;<i>Base</i>&gt;&gt;</del>&gt;;

  constexpr decltype(auto) operator*() const { return *<i>inner_</i>; }
  
  constexpr <ins><i>InnerIter</i></ins><del>iterator_t&lt;<i>Base</i>&gt;</del> operator-&gt;() const
    requires <i>has-arrow</i>&lt;<ins><i>InnerIter</i></ins><del>iterator_t&lt;<i>Base</i>&gt;</del>&gt; 
      &amp;&amp; copyable&lt;<ins><i>InnerIter</i></ins><del>iterator_t&lt;<i>Base</i>&gt;</del>&gt;;
  
  constexpr <i>iterator</i>&amp; operator++();
  [&hellip;]
</pre>
</blockquote>
<p>
[&hellip;]
</p>
<pre>
constexpr void <i>satisfy</i>(); <i>// exposition only</i>
</pre>
<blockquote>
<p>
-5- <i>Effects:</i> Equivalent to:
</p>
<blockquote><pre>
[&hellip;]
if constexpr (<i>ref-is-glvalue</i>)
  <i>inner_</i> = <ins><i>InnerIter</i></ins><del>iterator_t&lt;range_reference_t&lt;<i>Base</i>&gt;&gt;</del>();
</pre></blockquote>
</blockquote>
<pre>
constexpr <i>iterator</i>(<i>Parent</i>&amp; parent, <ins><i>OuterIter</i></ins><del>iterator_t&lt;<i>Base</i>&gt;</del> outer);
</pre>
<blockquote>
<p>
[&hellip;]
</p>
</blockquote>
<pre>
constexpr <i>iterator</i>(<i>iterator</i>&lt;!Const&gt; i)
  requires Const &amp;&amp;
           convertible_to&lt;iterator_t&lt;V&gt;, <ins><i>OuterIter</i></ins><del>iterator_t&lt;<i>Base</i>&gt;</del>&gt; &amp;&amp;
           convertible_to&lt;iterator_t&lt;<i>InnerRng</i>&gt;,
                          <ins><i>InnerIter</i></ins><del>iterator_t&lt;range_reference_t&lt;<i>Base</i>&gt;&gt;</del>&gt;;
</pre>
<blockquote>
<p>
[&hellip;]
</p>
</blockquote>
<pre>
constexpr <ins><i>InnerIter</i></ins><del>iterator_t&lt;<i>Base</i>&gt;</del> operator-&gt;() const
  requires <i>has-arrow</i>&lt;<ins><i>InnerIter</i></ins><del>iterator_t&lt;<i>Base</i>&gt;</del>&gt; 
    &amp;&amp; copyable&lt;<ins><i>InnerIter</i></ins><del>iterator_t&lt;<i>Base</i>&gt;</del>&gt;;
</pre>
<blockquote>
<p>
-8- <i>Effects:</i> Equivalent to <tt>return <i>inner_</i>;</tt>
</p>
</blockquote>
</blockquote>
</li>
</ol>





<hr>
<h3><a name="3502" href="https://cplusplus.github.io/LWG/lwg-active.html#3502">3502</a>. <tt>elements_view</tt> should not be allowed to return dangling references</h3>
<p><b>Section:</b> 24.7.16.3 <a href="https://wg21.link/range.elements.iterator">[range.elements.iterator]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Tim Song <b>Opened:</b> 2020-11-18 <b>Last modified:</b> 2021-02-08</p>
<p><b>Priority: </b>2
</p>
<p><b>View other</b> <a href="https://cplusplus.github.io/LWG/lwg-index-open.html#range.elements.iterator">active issues</a> in [range.elements.iterator].</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#range.elements.iterator">issues</a> in [range.elements.iterator].</p>
<p><b>Discussion:</b></p>
<p>
This compiles but the resulting view is full of dangling references:
</p>
<blockquote><pre>
std::vector&lt;int&gt; vec = {42};
auto r = vec | std::views::transform([](auto c) { return std::make_tuple(c, c); })
             | std::views::keys;
</pre></blockquote>
<p>
This is because <tt>elements_view::iterator::operator*</tt> is specified as
</p>
<blockquote><pre>
constexpr decltype(auto) operator*() const { return get&lt;N&gt;(*<i>current_</i>); }
</pre></blockquote>
<p>
Here <tt>*<i>current_</i></tt> is a prvalue, and so the <tt>get&lt;N&gt;</tt> produces a reference
into the materialized temporary that becomes dangling as soon as <tt>operator*</tt> returns.
<p/>
We should either ban this case altogether, or make <tt>operator*</tt> (and <tt>operator[]</tt>) return by
value when <tt>*<i>current_</i></tt> is a prvalue and the corresponding tuple element is not a reference 
(since this <tt>get</tt> is <tt>std::get</tt>, we need not worry about weird user-defined overloads.)
</p>

<p><i>[2020-11-29; Reflector prioritization]</i></p>

<p>
Set priority to 2 during reflector discussions.
</p>

<p><i>[2021-01-31 Tim adds PR]</i></p>


<p><i>[2021-02-08; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after six votes in favour during reflector poll.
</p>



<p><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/n4878">N4878</a>.
</p>

<ol>
<li><p>Modify 24.7.16.2 <a href="https://wg21.link/range.elements.view">[range.elements.view]</a>, as indicated:</p>

<blockquote>
<pre>
namespace std::ranges {
  template&lt;class T, size_t N&gt;
    concept <i>has-tuple-element</i> =                   // exposition only
      requires(T t) {
        typename tuple_size&lt;T&gt;::type;
        requires N &lt; tuple_size_v&lt;T&gt;;
        typename tuple_element_t&lt;N, T&gt;;
        { get&lt;N&gt;(t) } -&gt; convertible_to&lt;const tuple_element_t&lt;N, T&gt;&amp;&gt;;
      };
    
<ins>  template&lt;class T, size_t N&gt;
  concept <i>returnable-element</i> = is_reference_v&lt;T&gt; || move_­constructible&lt;tuple_element_t&lt;N, T&gt;&gt;;</ins>

  template&lt;input_range V, size_t N&gt;
    requires view&lt;V&gt; &amp;&amp; <i>has-tuple-element</i>&lt;range_value_t&lt;V&gt;, N&gt; &amp;&amp;
             <i>has-tuple-element</i>&lt;remove_reference_t&lt;range_reference_t&lt;V&gt;&gt;, N&gt; <ins>&amp;&amp;</ins>
             <ins><i>returnable-element</i>&lt;range_reference_t&lt;V&gt;, N&gt;</ins>
  class elements_view : public view_interface&lt;elements_view&lt;V, N&gt;&gt; {
    [&hellip;]
  };
}
</pre>
</blockquote>
</li>
<li><p>Modify 24.7.16.3 <a href="https://wg21.link/range.elements.iterator">[range.elements.iterator]</a> as indicated:</p>
<blockquote>
<blockquote>
<pre>
namespace std::ranges {
  template&lt;input_range V, size_t N&gt;
    requires view&lt;V&gt; &amp;&amp; <i>has-tuple-element</i>&lt;range_value_t&lt;V&gt;, N&gt; &amp;&amp;
             <i>has-tuple-element</i>&lt;remove_reference_t&lt;range_reference_t&lt;V&gt;&gt;, N&gt; <ins>&amp;&amp;</ins>
             <ins><i>returnable-element</i>&lt;range_reference_t&lt;V&gt;, N&gt;</ins>
  template&lt;bool Const&gt;
  class elements_view&lt;V, N&gt;::<i>iterator</i> {                 // exposition only
    using <i>Base</i> = <i>maybe-const</i>&lt;Const, V&gt;;                 // exposition only

    iterator_t&lt;<i>Base</i>&gt; <i>current_</i> = iterator_t&lt;<i>Base</i>&gt;();<ins>     // exposition only</ins>
   
<ins>    static constexpr decltype(auto) <i>get-element</i>(const iterator_t&lt;<i>Base</i>&gt;&amp; i);    // exposition only</ins>
  public:
    [&hellip;]
    constexpr decltype(auto) operator*() const
    { return <del>get&lt;N&gt;</del><ins><i>get-element</i></ins>(<del>*</del><i>current_</i>); }

    [&hellip;]
    constexpr decltype(auto) operator[](difference_type n) const
    requires random_­access_­range&lt;<i>Base</i>&gt;
    { return <del>get&lt;N&gt;</del><ins><i>get-element</i></ins>(<del>*(</del><i>current_</i> + n<del>)</del>); }
  };
}
</pre>
</blockquote>
<pre>
<ins>static constexpr decltype(auto) <i>get-element</i>(const iterator_t&lt;<i>Base</i>&gt;&amp; i);    // exposition only</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Effects:</i> Equivalent to:</ins>
</p>
<blockquote>
<pre>
<ins>
if constexpr (is_reference_v&lt;range_reference_t&lt;<i>Base</i>&gt;&gt;) {
  return get&lt;N&gt;(*i);
}
else {
  using E = remove_cv_t&lt;tuple_element_t&lt;N, range_reference_t&lt;<i>Base</i>&gt;&gt;&gt;;
  return static_cast&lt;E&gt;(get&lt;N&gt;(*i));
}
</ins>
</pre>
</blockquote>
</blockquote>
</blockquote>
</li>

    
<li><p>Modify 24.7.16.4 <a href="https://wg21.link/range.elements.sentinel">[range.elements.sentinel]</a> as indicated:</p>
<blockquote>
<blockquote>
<pre>
namespace std::ranges {
  template&lt;input_range V, size_t N&gt;
    requires view&lt;V&gt; &amp;&amp; <i>has-tuple-element</i>&lt;range_value_t&lt;V&gt;, N&gt; &amp;&amp;
             <i>has-tuple-element</i>&lt;remove_reference_t&lt;range_reference_t&lt;V&gt;&gt;, N&gt; <ins>&amp;&amp;</ins>
             <ins><i>returnable-element</i>&lt;range_reference_t&lt;V&gt;, N&gt;</ins>
  template&lt;bool Const&gt;
  class elements_view&lt;V, N&gt;::<i>sentinel</i> {                 // exposition only
    [&hellip;]
  };
}
</pre>
</blockquote>
</blockquote>
</li>
</ol>





<hr>
<h3><a name="3505" href="https://cplusplus.github.io/LWG/lwg-active.html#3505">3505</a>. <tt>split_view::<i>outer-iterator</i>::operator++</tt> misspecified</h3>
<p><b>Section:</b> 24.7.12.3 <a href="https://wg21.link/range.split.outer">[range.split.outer]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Tim Song <b>Opened:</b> 2020-11-20 <b>Last modified:</b> 2021-02-08</p>
<p><b>Priority: </b>2
</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#range.split.outer">issues</a> in [range.split.outer].</p>
<p><b>Discussion:</b></p>
<p>
Prior to the application of <a href="https://wg21.link/p1862r1">P1862R1</a>, the part of
<tt>split_view::<i>outer-iterator</i>::operator++</tt> that searches for the pattern
is specified as:
</p>
<blockquote><pre>
do {
  const auto [b, p] = ranges::mismatch(<i>current</i>, end, pbegin, pend);
  if (p == pend) {
    <i>current</i> = b; // The pattern matched; skip it
    break;
  }
} while (++<i>current</i> != end);
</pre></blockquote>
<p>
<a href="https://wg21.link/p1862r1">P1862R1</a>, trying to accommodate move-only iterators, respecified this as
</p>
<blockquote><pre>
do {
  auto [b, p] = ranges::mismatch(std::move(<i>current</i>), end, pbegin, pend);
  <i>current</i> = std::move(b);
  if (p == pend) {
    break; // The pattern matched; skip it
  }
} while (++<i>current</i> != end);
</pre></blockquote>
<p>
but this is not correct, because if the pattern didn't match, it advances <tt><i>current</i></tt> 
to the point of first mismatch, skipping elements before that point. This is totally wrong if the 
pattern contains more than one element. 
<p/>
Consider <tt>std::views::split("xxyx"sv, "xy"sv)</tt>:
</p>
<ul>
<li><p>at the beginning, <tt><i>current</i></tt> points to the first <tt>'x'</tt></p></li>
<li><p><tt>ranges::mismatch</tt> produces <tt>[</tt>iterator to second <tt>'x'</tt>, 
iterator to <tt>'y'</tt> in pattern<tt>]</tt></p></li>
<li><p><tt><i>current</i></tt> now points to second <tt>'x'</tt></p></li>
<li><p>we increment <tt><i>current</i></tt> in the condition, so it now points to <tt>'y'</tt></p></li>
</ul>
<p>
At this point there's no way we can find the <tt>"xy"</tt> in the middle. In fact, 
in this particular example, we'll increment past the end of the source range at the 
end of the third iteration.
</p>

<p><i>[2020-11-29; Reflector prioritization]</i></p>

<p>
Set priority to 2 during reflector discussions.
</p>

<p><i>[2021-02-08; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after six votes in favour during reflector poll.
</p>



<p><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/n4868">N4868</a>. 
</p>

<ol>
<li>
<p>
Modify 24.7.12.3 <a href="https://wg21.link/range.split.outer">[range.split.outer]</a> as indicated:
</p>

<blockquote>
<pre>
constexpr <i>outer-iterator</i>&amp; operator++();
</pre>
<blockquote>
<p>
-6- <i>Effects:</i> Equivalent to:
</p>
<blockquote>
<pre>
const auto end = ranges::end(<i>parent_</i>-&gt;<i>base_</i>);
if (<i>current</i> == end) return <tt>*this</tt>;
const auto [pbegin, pend] = subrange{<i>parent_</i>-&gt;<i>pattern_</i>};
if (pbegin == pend) ++<i>current</i>;
<ins>else if constexpr (<i>tiny-range</i>&lt;Pattern&gt;) {
  <i>current</i> = ranges::find(std::move(<i>current</i>), end, *pbegin);
  if (<i>current</i> != end) {
    ++<i>current</i>;
  }
}</ins>
else {
  do {
    auto [b, p] = ranges::mismatch(<del>std::move(</del><i>current</i><del>)</del>, end, pbegin, pend);
    <del><i>current</i> = std::move(b);</del>
    if (p == pend) {
      <ins><i>current</i> = b;</ins>
      break; <i>// The pattern matched; skip it</i>
    }
  } while (++<i>current</i> != end);
}
return *this;
</pre>
</blockquote>
</blockquote>
</blockquote>
</li>
</ol>





</body>
</html>
