<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 4241: ranges::for_each(_n) should be less constrained</title>
<meta property="og:title" content="Issue 4241: ranges::for_each(_n) should be less constrained">
<meta property="og:description" content="C++ library issue. Status: New">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue4241.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#New">New</a> status.</em></p>
<h3 id="4241"><a href="lwg-active.html#4241">4241</a>. <code class='backtick'>ranges::for_each(_n)</code> should be less constrained</h3>
<p><b>Section:</b> 26.6.5 <a href="https://wg21.link/alg.foreach">[alg.foreach]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a>
 <b>Submitter:</b> Jiang An <b>Opened:</b> 2025-04-08 <b>Last modified:</b> 2025-04-13</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View other</b> <a href="lwg-index-open.html#alg.foreach">active issues</a> in [alg.foreach].</p>
<p><b>View all other</b> <a href="lwg-index.html#alg.foreach">issues</a> in [alg.foreach].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#New">New</a> status.</p>
<p><b>Discussion:</b></p>
<p>
Currently, <code class='backtick'>ranges::for_each(_n)</code> are constrained with <code class='backtick'>indirectly_unary_invocable</code>, 
which doesn't meet the actual use of the range elements. These algorithms are only 
expected to invoke the callable object with the possibly projected elements, and not 
to use any element as the value type. Moreover, <code class='backtick'>indirectly_unary_invocable</code> requires 
the callable object to be copy constructible, which might be undesired because the 
corresponding <code class='backtick'>std::for_each(_n)</code> only require move constructibilty.
<p/>
LWG <a href="lwg-active.html#4171" title="P2609R3 breaks code that uses views::zip and get&lt;T&gt; (Status: New)">4171</a><sup><a href="https://cplusplus.github.io/LWG/issue4171" title="Latest snapshot">(i)</a></sup> talked about the breakage around <code class='backtick'>ranges::for_each</code> introduced 
by <a href="https://wg21.link/P2609R3" title=" Relaxing Ranges Just A Smidge">P2609R3</a>. P2609R3 looks like a reasonable fix as long as the affected 
algorithms potentially use the intermediate element values copied as 
<code>std::iter_value_t&lt;I&gt;</code>. However, when the algorithm is not expected to or 
even required not to do this, P2609R3 can bring unexpected impacts. It seems that 
constraints around <code class='backtick'>iter_value_t</code> should be avoided for such an algorithm.
</p>


<p id="res-4241"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N5008" title=" Working Draft, Programming Languages — C++">N5008</a>.
</p>

<ol>

<li><p>Modify 26.4 <a href="https://wg21.link/algorithm.syn">[algorithm.syn]</a>, header <code>&lt;algorithm&gt;</code> synopsis, as indicated:</p>

<blockquote>
<pre>
[&hellip;]
namespace ranges {
  template&lt;class I, class F&gt;
  using for_each_result = in_fun_result&lt;I, F&gt;;
  
  template&lt;input_iterator I, sentinel_for&lt;I&gt; S, class Proj = identity,
           <del>indirectly_unary_invocable&lt;projected&lt;I, Proj&gt;&gt;</del><ins>move_constructible</ins> Fun&gt;
    <ins>requires invocable&lt;Fun&amp;, iter_reference_t&lt;projected&lt;I, Proj&gt;&gt;&gt;</ins>
    constexpr for_each_result&lt;I, Fun&gt;
      for_each(I first, S last, Fun f, Proj proj = {});
  template&lt;input_range R, class Proj = identity,
           <del>indirectly_unary_invocable&lt;projected&lt;iterator_t&lt;R&gt;, Proj&gt;&gt;</del><ins>move_constructible</ins> Fun&gt;
    <ins>requires invocable&lt;Fun&amp;, iter_reference_t&lt;projected&lt;iterator_t&lt;R&gt;, Proj&gt;&gt;&gt;</ins>
    constexpr for_each_result&lt;borrowed_iterator_t&lt;R&gt;, Fun&gt;
      for_each(R&amp;&amp; r, Fun f, Proj proj = {});
}
[&hellip;]
namespace ranges {
  template&lt;class I, class F&gt;
  using for_each_n_result = in_fun_result&lt;I, F&gt;;

  template&lt;input_iterator I, class Proj = identity,
           <del>indirectly_unary_invocable&lt;projected&lt;I, Proj&gt;&gt;</del><ins>move_constructible</ins> Fun&gt;
     <ins>requires invocable&lt;Fun&amp;, iter_reference_t&lt;projected&lt;I, Proj&gt;&gt;&gt;</ins>
    constexpr for_each_n_result&lt;I, Fun&gt;
      for_each_n(I first, iter_difference_t&lt;I&gt; n, Fun f, Proj proj = {});
}
[&hellip;]
</pre>
</blockquote>

</li>

<li><p>Modify 26.6.5 <a href="https://wg21.link/alg.foreach">[alg.foreach]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;input_iterator I, sentinel_for&lt;I&gt; S, class Proj = identity,
         <del>indirectly_unary_invocable&lt;projected&lt;I, Proj&gt;&gt;</del><ins>move_constructible</ins> Fun&gt;
  <ins>requires invocable&lt;Fun&amp;, iter_reference_t&lt;projected&lt;I, Proj&gt;&gt;&gt;</ins>
  constexpr ranges::for_each_result&lt;I, Fun&gt;
    ranges::for_each(I first, S last, Fun f, Proj proj = {});
template&lt;input_range R, class Proj = identity,
         <del>indirectly_unary_invocable&lt;projected&lt;iterator_t&lt;R&gt;, Proj&gt;&gt;</del><ins>move_constructible</ins> Fun&gt;
  <ins>requires invocable&lt;Fun&amp;, iter_reference_t&lt;projected&lt;iterator_t&lt;R&gt;, Proj&gt;&gt;&gt;</ins>
  constexpr ranges::for_each_result&lt;borrowed_iterator_t&lt;R&gt;, Fun&gt;
    ranges::for_each(R&amp;&amp; r, Fun f, Proj proj = {});
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
<del>-15- [<i>Note 6</i>: The overloads in namespace <code class='backtick'>ranges</code> require <code class='backtick'>Fun</code> to model <code class='backtick'>copy_constructible</code>. &mdash; <i>end note</i>]</del>
</p>
</blockquote>
<p>
[&hellip;]
</p>
<pre>
template&lt;input_iterator I, class Proj = identity,
         <del>indirectly_unary_invocable&lt;projected&lt;I, Proj&gt;&gt;</del><ins>move_constructible</ins> Fun&gt;
  <ins>requires invocable&lt;Fun&amp;, iter_reference_t&lt;projected&lt;I, Proj&gt;&gt;&gt;</ins>
  constexpr ranges::for_each_n_result&lt;I, Fun&gt;
    ranges::for_each_n(I first, iter_difference_t&lt;I&gt; n, Fun f, Proj proj = {});
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
<del>-30- [<i>Note 11</i>: The overload in namespace <code class='backtick'>ranges</code> requires <code class='backtick'>Fun</code> to model <code class='backtick'>copy_constructible</code>. &mdash; <i>end note</i>]</del>
</p>
</blockquote>
</blockquote>

</li>

</ol>





</body>
</html>
