<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <meta name="generator" content="pandoc" />
  <title>Ready Ranges TS Issues</title>
  <style type="text/css">code{white-space: pre;}</style>
  <style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
  margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
  </style>
  <style type="text/css">
  ins {
    background-color: lime; text-decoration:underline;
  }
  
  del {
    background-color: #ff8080; text-decoration:line-through;
  }
  
  ednote {
    color:blue;
  }
  
  table {
    border-collapse: collapse;
  }
  
  table, th, td {
    border: 1px solid black;
  }
  </style>
</head>
<body>
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="607">
  <tr>
    <td width="172" align="left" valign="top">Document number:</td>
    <td width="435">
      P0621R0
    </td>
  </tr>
  <tr>
    <td width="172" align="left" valign="top">Date:</td>
    <td width="435">2017-03-02</td>
  </tr>
  <tr>
    <td width="172" align="left" valign="top">Project:</td>
    <td width="435">C++ Extensions for Ranges, Library Working Group</td>
  </tr>
  <tr>
    <td width="172" align="left" valign="top">Reply-to:</td>
    <td width="435">
      Casey Carter &lt;<a href="mailto:Casey@Carter.net">Casey@Carter.net</a>&gt;<br>
    </td>
  </tr>
</table>
<div id="header">
<h1 class="title">Ready Ranges TS Issues</h1>
</div>
<h2 id="remove-subsection-c-library-algorithms-from-experimentalrangesalgorithm"><a href="https://github.com/ericniebler/stl2/issues/258">258</a>: Remove subsection “C library algorithms” from <code>&lt;experimental/ranges/algorithm&gt;</code></h2>
<p>The C library is not in scope for the TS, this material was inadvertently incorporated by editorial error.</p>
<h4 id="proposed-resolution">Proposed Resolution</h4>
<p>Strike section [alg.c.library]. Remove the reference thereto in Table 62 and in the descriptive text in [algorithms.general]/2.</p>
<h2 id="move_iteratoroperator-should-be-defined-in-terms-of-iter_move"><a href="https://github.com/ericniebler/stl2/issues/244">244</a> <code>move_iterator::operator*</code> should be defined in terms of <code>iter_move</code></h2>
<p>This change is required for correct behavior of <code>move_iterator&lt;I&gt;</code> when <code>I</code> is a proxy iterator, it was overlooked by P0022.</p>
<h4 id="proposed-resolution-1">Proposed Resolution</h4>
<p>Change the synopsis of class <code>move_iterator</code> in [move.iterator]:</p>
<blockquote>
<p><tt>template &lt;InputIterator I&gt;</tt><br />
<tt>class move_iterator {</tt><br />
<tt>public:</tt><br />
  […]<br />
<tt>  using iterator_category = input_iterator_tag;</tt><br />
<tt>  using reference = <ins>rvalue_reference_t&lt;I&gt;</ins><del><i>see below</i></del>;</tt><br />
<tt>  move_iterator();</tt><br />
  […]<br />
<tt>};</tt></p>
</blockquote>
<p>Delete paragraph 1:</p>
<blockquote>
<p>1 <del>Let <tt>R</tt> be <tt>reference_t&lt;I&gt;</tt>. If <tt>is_reference&lt;R&gt;::value</tt> is <tt>true</tt>, the template specialization <tt>move_iterator&lt;I&gt;</tt> shall define the nested type named reference as a synonym for <tt>remove_reference_t&lt;R&gt;&amp;&amp;</tt>, otherwise as a synonym for <tt>R</tt>.</del></p>
</blockquote>
<p>Change the description of <code>move_iterator::operator*</code> in [move.iter.op.star] as follows:</p>
<blockquote>
<p>1 <em>Effects:</em> Equivalent to<ins>: <tt>return iter_move(current);</tt></ins> <del><tt>static_cast&lt;reference&gt;(*current)</tt>.</del></p>
</blockquote>
<p>Change the description of <code>move_iterator::operator[]</code> in [move.iter.op.star] as follows:</p>
<blockquote>
<p>1 <em>Effects:</em> Equivalent to: <tt>return <ins>iter_move(i + n);</ins><del>static_cast&lt;reference&gt;(current[n]);</del></tt></p>
</blockquote>
<h2 id="difference_type-of-arrays"><a href="https://github.com/ericniebler/stl2/issues/243">243</a> <code>difference_type</code> of arrays</h2>
<p>The <code>is_array</code> specialization for <code>difference_type</code> is extraneous; the fallback/deducing specialization handles array types properly.</p>
<h4 id="proposed-resolution-2">Proposed Resolution</h4>
<p>Change [iterator.traits]/4 as follows:</p>
<blockquote>
<p>  […]</p>
<p><tt>template &lt;class T&gt;</tt><br />
<tt>struct difference_type&lt;T*&gt;</tt><br />
<tt>  : enable_if&lt;is_object&lt;T&gt;::value, ptrdiff_t&gt; { };</tt></p>
<p><tt><del>template &lt;class I&gt;</del></tt><br />
<del><tt>  requires is_array&lt;I&gt;::value</tt></del><br />
<del><tt>struct difference_type&lt;I&gt; : difference_type&lt;decay_t&lt;I&gt;&gt; { };</tt></del></p>
<p><tt>template &lt;class I&gt;</tt><br />
<tt>struct difference_type&lt;I const&gt; : difference_type&lt;decay_t&lt;I&gt;&gt; { };</tt></p>
<p>  […]</p>
</blockquote>
<h2 id="customizing-iter_move-and-iter_swap-is-needlessly-complicated"><a href="https://github.com/ericniebler/stl2/issues/242">242</a> Customizing <code>iter_move</code> and <code>iter_swap</code> is needlessly complicated</h2>
<p>The specifications of <code>iter_move</code> and <code>iter_swap</code> require user customizations found via ADL to compete in overload resolution with the “default” implementations which are constrained functions that accept forwarding references. This makes it challenging for users who are not expert in the rules for partial ordering of constrained function templates to hook the customization points.</p>
<h4 id="proposed-resolution-3">Proposed Resolution</h4>
<p>Replace the text of [iterator.utils.iter_move] with the following:</p>
<blockquote>
<p>1. The name <code>iter_move</code> denotes a <em>customization point object</em> ([customization.point.object]). The effect of the expression <code>ranges::iter_move(E)</code> for some expression <code>E</code> is equivalent to the following:</p>
<p>2. <code>iter_move(E)</code>, if that expression is well-formed when evaluated in a context that does not include <code>ranges::iter_move</code> but does include the lookup set produced by argument-dependent lookup ([basic.lookup.argdep]).</p>
<p>3. Otherwise, if <code>E</code> is dereferenceable<br />
(3.1) If <code>*E</code> is an lvalue, <code>std::move(*E)</code><br />
(3.2) Otherwise, <code>*E</code></p>
<p>4. Otherwise, <code>ranges::iter_move(E)</code> is ill-formed.</p>
<p>5. If <code>ranges::iter_move(E)</code> does not equal <code>*E</code>, the program is ill-formed with no diagnostic required.</p>
</blockquote>
<p>Replace the text of [iterator.utils.iter_swap] with the following:</p>
<blockquote>
<p>1. The name <code>iter_swap</code> denotes a <em>customization point object</em> ([customization.point.object]). The effect of the expression <code>ranges::iter_swap(E1, E2)</code> for some expressions <code>E1</code> and <code>E2</code> is equivalent to the following:</p>
<p>2. <code>(void)iter_swap(E1, E2)</code>, if that expression is well-formed when evaluated in a context that does not include <code>ranges::iter_swap</code> but does include the lookup set produced by argument-dependent lookup ([basic.lookup.argdep]) and the following declaration:</p>
<blockquote>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="dt">void</span> iter_swap(<span class="kw">auto</span>, <span class="kw">auto</span>) = <span class="kw">delete</span>;</code></pre></div>
</blockquote>
<p>3. Otherwise, if the expressions <code>E1</code> and <code>E2</code> both satisfy <code>Readable</code>, and if the reference type of <code>E1</code> is swappable with ([concepts.lib.corelang.swappable) the reference type of <code>E2</code>, then <code>ranges::swap(*E1, *E2)</code></p>
<p>4. Otherwise, if the types <code>T1</code> and <code>T2</code> of <code>E1</code> and <code>E2</code> satisfy <code>IndirectlyMovableStorable&lt;T1, T2&gt;() &amp;&amp; IndirectlyMovableStorable&lt;T2, T1&gt;()</code>, exchanges the values denoted by <code>E1</code> and <code>E2</code>.<br />
(4.1) <code>ranges::iter_swap(E1, E2)</code> is a constant expression if and only if <code>E1</code> and <code>E2</code> are constant expressions and the required operations of <code>IndirectlyMovableStorable&lt;T1, T2&gt;()</code> and <code>IndirectlyMovableStorable&lt;T2, T1&gt;()</code> are constant expressions.<br />
(4.2) <code>ranges::iter_swap(E1, E2)</code> is <code>noexcept</code> if and only if <code>E1</code> and <code>E2</code> are <code>noexcept</code> and the required operations of <code>IndirectlyMovableStorable&lt;T1, T2&gt;()</code> and <code>IndirectlyMovableStorable&lt;T2, T1&gt;()</code> are <code>noexcept</code>.</p>
<p>5. Otherwise, <code>ranges::iter_swap(E1, E2)</code> is ill-formed.</p>
<p>6. If <code>ranges::iter_swap(E1, E2)</code> does not swap the values denoted by the expressions <code>E1</code> and <code>E2</code>, the program is ill-formed with no diagnostic required.</p>
</blockquote>
<h2 id="indirectlyswappable-is-broken"><a href="https://github.com/ericniebler/stl2/issues/241">241</a> <code>IndirectlySwappable</code> is broken</h2>
<p><code>IndirectlySwappable</code> as defined in N4620:</p>
<blockquote>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">template</span> &lt;<span class="kw">class</span> I1, <span class="kw">class</span> I2 = I1&gt;
concept <span class="dt">bool</span> IndirectlySwappable() {
  <span class="kw">return</span> Readable&lt;I1&gt;() &amp;&amp; Readable&lt;I2&gt;() &amp;&amp;
    requires (<span class="dt">const</span> I1 i1, <span class="dt">const</span> I2 i2) {
      ranges::iter_swap(i1, i2);
      ranges::iter_swap(i2, i1);
      ranges::iter_swap(i1, i1);
      ranges::iter_swap(i2, i2);
    };
}</code></pre></div>
</blockquote>
<p>Requires that it is possible to <code>iter_swap</code> <em>constant</em> <code>I1</code> and <code>I2</code>. This indirectly requires <code>Readable&lt;const I1&gt;</code> and <code>Writable&lt;const I1&gt;</code> (resp. <code>I2</code>) both of which require <code>Movable</code>. Since constant objects cannot be the target of assignment operations, <code>Movable&lt;const I1&gt;</code> (resp. <code>I2</code>) is not satisfied. This issue only manifests when <code>I1</code> and <code>I2</code> are non-reference types, creating a confusing discrepancy between <code>IndirectlySwappable&lt;Foo, Bar&gt;</code> and <code>IndirectlySwappable&lt;Foo&amp;&amp;, Bar&gt;</code>.</p>
<p>This problem does not manifest in the implementations because neither applies <code>const</code> to the parameter types before passing them to <code>iter_swap</code>.</p>
<p><code>IndirectlySwappable&lt;int[2], int[4]&gt;()</code> is also incorrectly satisfied due to array-to-pointer decay of function (and hence requires expression) parameters. This should be corrected by accepting the requires clause parameters by forwarding reference.</p>
<h4 id="proposed-resolution-4">Proposed Resolution</h4>
<p>Change the definition of <code>IndirectlySwappable</code> in [commonalgoreq.indirectlyswappable] as follows:</p>
<blockquote>
<p><tt>template &lt;class I1, class I2 = I1&gt;</tt><br />
<tt>concept bool IndirectlySwappable() {</tt><br />
<tt>  return Readable&lt;I1&gt;() &amp;&amp; Readable&lt;I2&gt;() &amp;&amp;</tt><br />
<tt>    <del>requires (const I1 i1, const I2 i2) {</del></tt><br />
<tt>      <del>ranges::iter_swap(i1, i2);</del></tt><br />
<tt>      <del>ranges::iter_swap(i2, i1);</del></tt><br />
<tt>      <del>ranges::iter_swap(i1, i1);</del></tt><br />
<tt>      <del>ranges::iter_swap(i2, i2);</del></tt><br />
<tt>    <ins>requires (I1&amp;&amp; i1, I2&amp;&amp; i2) {</ins></tt><br />
<tt>      <ins>ranges::iter_swap(std::forward&lt;I1&gt;(i1), std::forward&lt;I2&gt;(i2));</ins></tt><br />
<tt>      <ins>ranges::iter_swap(std::forward&lt;I2&gt;(i2), std::forward&lt;I1&gt;(i1));</ins></tt><br />
<tt>      <ins>ranges::iter_swap(std::forward&lt;I1&gt;(i1), std::forward&lt;I1&gt;(i1));</ins></tt><br />
<tt>      <ins>ranges::iter_swap(std::forward&lt;I2&gt;(i2), std::forward&lt;I2&gt;(i2));</ins></tt><br />
<tt>    };</tt><br />
<tt>}</tt></p>
</blockquote>
<h2 id="should-writable-require-semiregular-or-move-defaultable"><a href="https://github.com/ericniebler/stl2/issues/240">240</a> Should <code>Writable</code> require <code>Semiregular</code>, or “Move-Defaultable”</h2>
<p>P0022R2 changed the <code>Readable</code> concept by replacing the <code>Semiregular</code> requirement with <code>Movable</code> and <code>DefaultConstructible</code>; this allows move-only types like <code>unique_ptr&lt;int&gt;</code> and <code>optional&lt;thread&gt;</code> to model <code>Readable</code>.</p>
<p>P0022R2 notably did <em>not</em> make the symmetric change to the <code>Writable</code> concept. Why should it be forbidden to write to these move-only types from which I may read?</p>
<p>Note that this discrepancy is exacerbated by the fact that both implementations (<a href="https://github.com/CaseyCarter/cmcstl2/blob/master/include/stl2/detail/iterator/concepts.hpp#L223">cmcstl2</a>, <a href="https://github.com/ericniebler/range-v3/blob/master/include/range/v3/utility/iterator_concepts.hpp#L176">range-v3</a>) of the TS have <em>already</em> implemented the same relaxation for <code>Writable</code>.</p>
<h4 id="proposed-resolution-5">Proposed Resolution</h4>
<p>Modify the definition of <code>Writable</code> ([iterators.writable]) as follows:</p>
<blockquote>
<p><tt>template &lt;class Out, class T&gt;</tt><br />
<tt>concept bool Writable() {</tt><br />
<tt>  <del>return Semiregular&lt;Out&gt;() &amp;&amp;</del></tt><br />
<tt>  <ins>return Movable&lt;Out&gt;() &amp;&amp; DefaultConstructible&lt;Out&gt;() &amp;&amp;</del></tt><br />
<tt>    requires(Out o, T&amp;&amp; t) {</tt><br />
<tt>      *o = std::forward&lt;T&gt;(t); // not required to be equality preserving</tt><br />
<tt>    };</tt><br />
<tt>}</tt></p>
</blockquote>
<h2 id="remove-the-experimental-additional-constraints-from-readable"><a href="https://github.com/ericniebler/stl2/issues/239">239</a> Remove the “Experimental additional constraints” from <code>Readable</code></h2>
<p>From <a href="https://github.com/ericniebler/stl2/issues/183">#183</a>:</p>
<blockquote>
<p>We can probably just remove these sanity checks from range-v3, cmcstl2, and the Ranges TS. I added them to keep myself honest when I was designing and implementing proxy iterator support. Now they only serve to make compile times worse. Holler if you see a reason to keep them.</p>
</blockquote>
<p>I see no reason to keep them; we should strike those requirements from P0022 before moving it into the TS.</p>
<h4 id="proposed-resolution-6">Proposed Resolution:</h4>
<p>Wording relative to P0022R2. Change the definition of the <code>Readable</code> concept in [iterators.readable] as follows:</p>
<blockquote>
<p><tt>template &lt;class I&gt;</tt><br />
<tt>concept bool Readable() {</tt><br />
<tt>  return Movable&lt;I&gt;() &amp;&amp; DefaultConstructible&lt;I&gt;() &amp;&amp;</tt><br />
<tt>    requires (const I&amp; i) {</tt><br />
<tt>      typename value_type_t&lt;I&gt;;</tt><br />
<tt>      typename reference_t&lt;I&gt;;</tt><br />
<tt>      typename rvalue_reference_t&lt;I&gt;;</tt><br />
<tt>      { *i } -&gt; Same&lt;reference_t&lt;I&gt;&gt;;</tt><br />
<tt>      { iter_move(i) } -&gt; Same&lt;rvalue_reference_t&lt;I&gt;&gt;;</tt><br />
<tt>    } &amp;&amp;</tt><br />
<tt>    // Relationships between associated types</tt><br />
<tt>    CommonReference&lt;reference_t&lt;I&gt;, value_type_t&lt;I&gt;&amp;&gt;() &amp;&amp;</tt><br />
<tt>    CommonReference&lt;reference_t&lt;I&gt;, rvalue_reference_t&lt;I&gt;&gt;() &amp;&amp;</tt><br />
<tt>    CommonReference&lt;rvalue_reference_t&lt;I&gt;, const value_type_t&lt;I&gt;&amp;&gt;()<ins>;</ins> <del>&amp;&amp;</del></tt><br />
<tt>    <del>Same&lt;</del></tt><br />
<tt>      <del>common_reference_t&lt;reference_t&lt;I&gt;, value_type_t&lt;I&gt;&gt;,</del></tt><br />
<tt>      <del>value_type_t&lt;I&gt;&gt;() &amp;&amp;</del></tt><br />
<tt>    <del>Same&lt;</del></tt><br />
<tt>      <del>common_reference_t&lt;rvalue_reference_t&lt;I&gt;, value_type_t&lt;I&gt;&gt;,</del></tt><br />
<tt>      <del>value_type_t&lt;I&gt;&gt;();</del></tt><br />
<tt>}</tt></p>
</blockquote>
<h2 id="p0022-broke-indirect_result_of"><a href="https://github.com/ericniebler/stl2/issues/238">238</a> P0022 broke <code>indirect_result_of</code></h2>
<p>By removing my undocumented fix to <code>indirect_result_of</code> that <code>remove_reference</code>s the function type before passing it to <code>IndirectCallable</code>:</p>
<blockquote>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">template</span> &lt;<span class="kw">class</span> F, <span class="kw">class</span>... Is&gt;
  requires IndirectCallable&lt;remove_reference_t&lt;F&gt;, Is...&gt;()
<span class="kw">struct</span> indirect_result_of&lt;F(Is...)&gt; :
  result_of&lt;F(value_type_t&lt;Is&gt;...)&gt; { };</code></pre></div>
</blockquote>
<p>Without that <code>remove_reference_t</code>, when <code>F</code> is a reference type, we require the trivially satisfiable <code>CopyConstructible&lt;F&gt;</code> instead of the desired <code>CopyConstructible&lt;remove_reference_t&lt;F&gt;&gt;</code>.</p>
<p><code>indirect_result_of</code> is used directly in the declarations of the <code>transform</code> algorithms, and in <code>projected</code>. As a a result, after the change, <code>transform</code> doesn’t properly require the transformation function - and no algorithm properly requires its projection arguments - to be <code>CopyConstructible</code>.</p>
<h4 id="proposed-resolution-7">Proposed Resolution:</h4>
<p>In section [indirectcallables.indirectfunc], change the definition of <code>indirect_result_of</code> to read:</p>
<blockquote>
<p><tt>template &lt;class F, class... Is&gt;</tt><br />
<tt>    requires IndirectCallable&lt;<ins>decay_t&lt;</ins>F<ins>&gt;</ins>, Is...&gt;()</tt><br />
<tt>struct indirect_result_of&lt;F(Is...)&gt; :</tt><br />
<tt>    result_of&lt;F(reference_t&lt;Is&gt;...)&gt; { };</tt></p>
</blockquote>
<h2 id="indirectcallable-should-use-value_type_ti-instead-of-value_type_ti"><a href="https://github.com/ericniebler/stl2/issues/237">237</a> <code>IndirectCallable</code> should use <code>value_type_t&lt;I&gt;&amp;</code> instead of <code>value_type_t&lt;I&gt;</code></h2>
<p>In the Proxy Iterators paper, <code>IndirectCallable</code> is defined as:</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">template</span> &lt;<span class="kw">class</span> F, <span class="kw">class</span> I&gt;
concept <span class="dt">bool</span> IndirectCallable() {
    <span class="kw">return</span> Readable&lt;I&gt;() &amp;&amp;
        Callable&lt;F, value_type_t&lt;I&gt;&gt;() &amp;&amp;
        Callable&lt;F, reference_t&lt;I&gt;&gt;() &amp;&amp;
        Callable&lt;F, iter_common_reference_t&lt;I&gt;&gt;();
}</code></pre></div>
<p>I strongly suspect this should be:</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">template</span> &lt;<span class="kw">class</span> F, <span class="kw">class</span> I&gt;
concept <span class="dt">bool</span> IndirectCallable() {
    <span class="kw">return</span> Readable&lt;I&gt;() &amp;&amp;
        Callable&lt;F, value_type_t&lt;I&gt;&amp;&gt;() &amp;&amp;
        Callable&lt;F, reference_t&lt;I&gt;&gt;() &amp;&amp;
        Callable&lt;F, iter_common_reference_t&lt;I&gt;&gt;();
}</code></pre></div>
<p>N.B. <code>value_type_t&lt;I&gt;&amp;</code>. In the rest of the section as well.</p>
<p>Reason: algorithms generally do not call predicates with rvalues of the value type. More often, they create a (non-<code>const</code>) local to cache a value, and then pass <em>that</em> to a predicate. Hence, <code>IndirectCallable</code> should be testing with <code>value_type_t&lt;I&gt;&amp;</code>.</p>
<h4 id="proposed-resolution-8">Proposed Resolution</h4>
<p>Change every instance of <code>value_type_t&lt;XXX&gt;</code> in [indirectcallables.indirectfunc] to <code>value_type_t&lt;XXX&gt;&amp;</code> (see #189 for detailed wording.)</p>
<h2 id="projectedivalue_type-incorrectly-decays-arrays-to-pointers"><a href="https://github.com/ericniebler/stl2/issues/236">236</a> <code>projected&lt;I&gt;::value_type</code> incorrectly decays arrays to pointers</h2>
<p>The following code does not compile with <code>projected</code> as it is currently defined in the latest draft.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="dt">int</span> matrix[<span class="dv">3</span>][<span class="dv">4</span>] = {};
std::experimental::ranges::for_each(matrix, [](<span class="dt">int</span>(&amp;)[<span class="dv">4</span>]){});</code></pre></div>
<h4 id="proposed-resolution-9">Proposed Resolution</h4>
<p>Modify the definition of <code>projected</code> in [projected] as follows:</p>
<blockquote>
<p><tt>template &lt;Readable I, IndirectRegularCallable&lt;I&gt; Proj&gt;</tt><br />
<tt>struct projected {</tt><br />
<tt>  using value_type = <del>decay_t</del><ins>remove_cv_t&lt;remove_reference_t</ins>&lt;indirect_result_of_t&lt;Proj&amp;(I)&gt;<ins>&gt;</ins>&gt;;</tt><br />
<tt>  indirect_result_of_t&lt;Proj&amp;(I)&gt; operator*() const;</tt><br />
<tt>};</tt></p>
</blockquote>
<h2 id="concept-callable-should-perfectly-forward-its-function-to-invoke"><a href="https://github.com/ericniebler/stl2/issues/189">189</a> concept <code>Callable</code> should perfectly forward its function to <code>invoke</code></h2>
<p>Originally, the function &amp; callable concepts treated functions as lvalues since the algorithms accept functions by value, and therefore <em>always</em> invoke lvalue expressions. Given that we will almost certainly be using the <code>Callable</code> concepts with non-algorithm library components, and we want to be somewhat consistent with <code>is_callable</code>, I think we have enough reason to change that behavior to perfectly forward. (See the github issue tracker for complete discusssion.)</p>
<h4 id="proposed-resolution-10">Proposed Resolution</h4>
<p>(The proposed resolution is relative to P0022R2 (proxy iterators) and also includes the resolution to #237.)</p>
<p>Change the definition of <code>Callable</code> in [concepts.lib.callables.regularcallable] as follows:</p>
<blockquote>
<p><tt>template &lt;class F, class… Args&gt;</tt><br />
<tt>concept bool Callable() {</tt><br />
<tt>  return <del>CopyConstructible&lt;F&gt;() &amp;&amp;</del></tt><br />
<tt>    requires(F<ins>&amp;&amp;</ins> f, Args&amp;&amp;... args) {</tt><br />
<tt>      invoke(<ins>std::forward&lt;F&gt;(</ins>f<ins>)</ins>, std::forward&lt;Args&gt;(args)...); // not required to be equality preserving</tt><br />
<tt>    };</tt><br />
<tt>}</tt></p>
</blockquote>
<p>Change the definition of <code>Predicate</code> in [concepts.lib.callables.predicate] as follows:</p>
<blockquote>
<p><tt>template &lt;class F, class… Args&gt;</tt><br />
<tt>concept bool Predicate() {</tt><br />
<tt>  return RegularCallable&lt;F, Args…&gt;() &amp;&amp;</tt><br />
<tt>    Boolean&lt;result_of_t&lt;F<del>&amp;</del>(Args…)&gt;&gt;();</tt><br />
<tt>}</tt></p>
</blockquote>
<p>Change the definition of <code>IndirectCallable</code> in [indirectcallables.indirectfunc] to:</p>
<blockquote>
<p><tt>template &lt;class F&gt;</tt><br />
<tt>concept bool IndirectCallable() {</tt><br />
<tt>  return <ins>CopyConstructible&lt;F&gt;() &amp;&amp;</ins> Callable&lt;F<ins>&amp;</ins>&gt;();</tt><br />
<tt>}</tt><br />
<tt>template &lt;class F, class I&gt;</tt><br />
<tt>concept bool IndirectCallable() {</tt><br />
<tt>  return Readable&lt;I&gt;() <ins>&amp;&amp; CopyConstructible&lt;F&gt;() &amp;&amp;</ins></tt><br />
<tt>    Callable&lt;F<ins>&amp;</ins>, value_type_t&lt;I&gt;<ins>&amp;</ins>&gt;() &amp;&amp;</tt><br />
<tt>    Callable&lt;F<ins>&amp;</ins>, reference_t&lt;I&gt;&gt;() &amp;&amp;</tt><br />
<tt>    Callable&lt;F<ins>&amp;</ins>, iter_common_reference_t&lt;I&gt;&gt;();</tt><br />
<tt>}</tt><br />
<tt>template &lt;class F, class I1, class I2&gt;</tt><br />
<tt>concept bool IndirectCallable() {</tt><br />
<tt>  return Readable&lt;I1&gt;() &amp;&amp; Readable&lt;I2&gt;() &amp;&amp;</tt><br />
<tt>    <ins>CopyConstructible&lt;F&gt;() &amp;&amp;</ins></tt><br />
<tt>    Callable&lt;F<ins>&amp;</ins>, value_type_t&lt;I1&gt;<ins>&amp;</ins>, value_type_t&lt;I2&gt;<ins>&amp;</ins>&gt;() &amp;&amp;</tt><br />
<tt>    Callable&lt;F<ins>&amp;</ins>, value_type_t&lt;I1&gt;<ins>&amp;</ins>, reference_t&lt;I2&gt;&gt;() &amp;&amp;</tt><br />
<tt>    Callable&lt;F<ins>&amp;</ins>, reference_t&lt;I1&gt;, value_type_t&lt;I2&gt;<ins>&amp;</ins>&gt;() &amp;&amp;</tt><br />
<tt>    Callable&lt;F<ins>&amp;</ins>, reference_t&lt;I1&gt;, reference_t&lt;I2&gt;&gt;() &amp;&amp;</tt><br />
<tt>    Callable&lt;F<ins>&amp;</ins>, iter_common_reference_t&lt;I1&gt;, iter_common_reference_t&lt;I2&gt;&gt;();</tt><br />
<tt>}</tt></p>
</blockquote>
<p>Change <code>IndirectRegularCallable</code> in likewise fashion.</p>
<p>Change <code>IndirectCallablePredicate</code> to:</p>
<blockquote>
<p><tt>template &lt;class F, class I&gt;</tt><br />
<tt>concept bool IndirectCallablePredicate() {</tt><br />
<tt>  return Readable&lt;I&gt;() &amp;&amp;</tt><br />
<tt>    <ins>CopyConstructible&lt;F&gt;() &amp;&amp;</ins></tt><br />
<tt>    Predicate&lt;F<ins>&amp;</ins>, value_type_t&lt;I&gt;<ins>&amp;</ins>&gt;() &amp;&amp;</tt><br />
<tt>    Predicate&lt;F<ins>&amp;</ins>, reference_t&lt;I&gt;&gt;() &amp;&amp;</tt><br />
<tt>    Predicate&lt;F<ins>&amp;</ins>, iter_common_reference_t&lt;I&gt;&gt;();</tt><br />
<tt>}</tt><br />
<tt>template &lt;class F, class I1, class I2&gt;</tt><br />
<tt>concept bool IndirectCallablePredicate() {</tt><br />
<tt>  return Readable&lt;I1&gt;() &amp;&amp; Readable&lt;I2&gt;() &amp;&amp;</tt><br />
<tt>    <ins>CopyConstructible&lt;F&gt;() &amp;&amp;</ins></tt><br />
<tt>    Predicate&lt;F<ins>&amp;</ins>, value_type_t&lt;I1&gt;<ins>&amp;</ins>, value_type_t&lt;I2&gt;<ins>&amp;</ins>&gt;() &amp;&amp;</tt><br />
<tt>    Predicate&lt;F<ins>&amp;</ins>, value_type_t&lt;I1&gt;<ins>&amp;</ins>, reference_t&lt;I2&gt;&gt;() &amp;&amp;</tt><br />
<tt>    Predicate&lt;F<ins>&amp;</ins>, reference_t&lt;I1&gt;, value_type_t&lt;I2&gt;<ins>&amp;</ins>&gt;() &amp;&amp;</tt><br />
<tt>    Predicate&lt;F<ins>&amp;</ins>, reference_t&lt;I1&gt;, reference_t&lt;I2&gt;&gt;() &amp;&amp;</tt><br />
<tt>    Predicate&lt;F<ins>&amp;</ins>, iter_common_reference_t&lt;I1&gt;, iter_common_reference_t&lt;I2&gt;&gt;();</tt><br />
<tt>}</tt></p>
</blockquote>
<p>Change <code>IndirectCallableRelation</code> to:</p>
<blockquote>
<p><tt>template &lt;class F, class I1, class I2 = I1&gt;</tt><br />
<tt>concept bool IndirectCallableRelation() {</tt><br />
<tt>  return Readable&lt;I1&gt;() &amp;&amp; Readable&lt;I2&gt;() &amp;&amp;</tt><br />
<tt>    <ins>CopyConstructible&lt;F&gt;() &amp;&amp;</ins></tt><br />
<tt>    Relation&lt;F<ins>&amp;</ins>, value_type_t&lt;I1&gt;<ins>&amp;</ins>, value_type_t&lt;I2&gt;<ins>&amp;</ins>&gt;() &amp;&amp;</tt><br />
<tt>    Relation&lt;F<ins>&amp;</ins>, value_type_t&lt;I1&gt;<ins>&amp;</ins>, reference_t&lt;I2&gt;&gt;() &amp;&amp;</tt><br />
<tt>    Relation&lt;F<ins>&amp;</ins>, reference_t&lt;I1&gt;, value_type_t&lt;I2&gt;<ins>&amp;</ins>&gt;() &amp;&amp;</tt><br />
<tt>    Relation&lt;F<ins>&amp;</ins>, reference_t&lt;I1&gt;, reference_t&lt;I2&gt;&gt;() &amp;&amp;</tt><br />
<tt>    Relation&lt;F<ins>&amp;</ins>, iter_common_reference_t&lt;I1&gt;, iter_common_reference_t&lt;I2&gt;&gt;();</tt><br />
<tt>}</tt></p>
</blockquote>
<p>Change <code>IndirectCallableStrictWeakOrder</code> to:</p>
<blockquote>
<p><tt>template &lt;class F, class I1, class I2 = I1&gt;</tt><br />
<tt>concept bool IndirectCallableStrictWeakOrder() {</tt><br />
<tt>  return Readable&lt;I1&gt;() &amp;&amp; Readable&lt;I2&gt;() &amp;&amp;</tt><br />
<tt>    <ins>CopyConstructible&lt;F&gt;() &amp;&amp;</ins></tt><br />
<tt>    StrictWeakOrder&lt;F<ins>&amp;</ins>, value_type_t&lt;I1&gt;<ins>&amp;</ins>, value_type_t&lt;I2&gt;<ins>&amp;</ins>&gt;() &amp;&amp;</tt><br />
<tt>    StrictWeakOrder&lt;F<ins>&amp;</ins>, value_type_t&lt;I1&gt;<ins>&amp;</ins>, reference_t&lt;I2&gt;&gt;() &amp;&amp;</tt><br />
<tt>    StrictWeakOrder&lt;F<ins>&amp;</ins>, reference_t&lt;I1&gt;, value_type_t&lt;I2&gt;<ins>&amp;</ins>&gt;() &amp;&amp;</tt><br />
<tt>    StrictWeakOrder&lt;F<ins>&amp;</ins>, reference_t&lt;I1&gt;, reference_t&lt;I2&gt;&gt;() &amp;&amp;</tt><br />
<tt>    StrictWeakOrder&lt;F<ins>&amp;</ins>, iter_common_reference_t&lt;I1&gt;, iter_common_reference_t&lt;I2&gt;&gt;();</tt><br />
<tt>}</tt></p>
</blockquote>
<p>Change the signatures of the <code>generate</code> and <code>generate_n</code> algorithms as follows:</p>
<blockquote>
<p><tt>template &lt;<del>Callable</del><ins>class</ins> F, <del>OutputIterator&lt;result_of_t&lt;F&amp;()&gt;&gt;</del><ins>Iterator</ins> O, Sentinel&lt;O&gt; S&gt;</tt><br />
<tt>    <ins>requires Callable&lt;F&amp;&gt;() &amp;&amp; Writable&lt;O, result_of_t&lt;F&amp;()&gt;&gt;()</ins></tt><br />
<tt>O generate(O first, S last, F gen);</tt></p>
<p><tt>template &lt;<del>Callable</del><ins>class</ins> F, <del>OutputRange&lt;result_of_t&lt;F&amp;()&gt;&gt;</del><ins>class</ins> Rng&gt;</tt><br />
<tt>    <ins>requires Callable&lt;F&amp;&gt;() &amp;&amp; OutputRange&lt;Rng, result_of_t&lt;F&amp;()&gt;&gt;()</ins></tt><br />
<tt>  safe_iterator_t&lt;Rng&gt;</tt><br />
<tt>    generate(Rng&amp;&amp; rng, F gen);</tt></p>
<p><tt>template &lt;<del>Callable</del><ins>class</ins> F, <del>OutputIterator&lt;result_of_t&lt;F&amp;()&gt;&gt;</del><ins>Iterator</ins> O&gt;</tt><br />
<tt>    <ins>requires Callable&lt;F&amp;&gt;() &amp;&amp; Writable&lt;O, result_of_t&lt;F&amp;()&gt;&gt;()</ins></tt><br />
<tt>  O generate_n(O first, difference_type_t&lt;O&gt; n, F gen);</tt></p>
</blockquote>
<div id="refs" class="references">

</div>
</body>
</html>
