<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 3058: Parallel adjacent_difference shouldn't require creating temporaries</title>
<meta property="og:title" content="Issue 3058: Parallel adjacent_difference shouldn't require creating temporaries">
<meta property="og:description" content="C++ library issue. Status: C++20">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue3058.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++20">C++20</a> status.</em></p>
<h3 id="3058"><a href="lwg-defects.html#3058">3058</a>. Parallel <code>adjacent_difference</code> shouldn't require creating temporaries</h3>
<p><b>Section:</b> 26.10.12 <a href="https://wg21.link/adjacent.difference">[adjacent.difference]</a> <b>Status:</b> <a href="lwg-active.html#C++20">C++20</a>
 <b>Submitter:</b> Billy O'Neal III <b>Opened:</b> 2018-02-02 <b>Last modified:</b> 2021-02-25</p>
<p><b>Priority: </b>3
</p>
<p><b>View all other</b> <a href="lwg-index.html#adjacent.difference">issues</a> in [adjacent.difference].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++20">C++20</a> status.</p>
<p><b>Discussion:</b></p>
<p>
Parallel <code>adjacent_difference</code> is presently specified to "create a temporary object whose
type is <code>ForwardIterator1</code>'s value type". Serial <code>adjacent_difference</code> does that
because it needs to work with input iterators, and needs to work when the destination range
exactly overlaps the input range. The parallel version requires forward iterators and doesn't
allow overlap, so it can avoid making these temporaries.
</p>

<p><i>[2018-02-13, Priority set to 3 after mailing list discussion]</i></p>


<p><i>[2018-3-14 Wednesday evening issues processing; remove 'const' before <code>minus</code> and move to Ready.]</i></p>


<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">
<p>This wording is relative to <a href="https://wg21.link/n4713">N4713</a>.</p>

<ol>
<li><p>Modify 26.10.12 <a href="https://wg21.link/adjacent.difference">[adjacent.difference]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;class InputIterator, class OutputIterator&gt;
  OutputIterator
    adjacent_difference(InputIterator first, InputIterator last, OutputIterator result);
template&lt;class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2&gt;
  ForwardIterator2
    adjacent_difference(ExecutionPolicy&amp;&amp; exec,
                        ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result);

template&lt;class InputIterator, class OutputIterator, class BinaryOperation&gt;
  OutputIterator
    adjacent_difference(InputIterator first, InputIterator last,
                        OutputIterator result, BinaryOperation binary_op);
template&lt;class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2,
         class BinaryOperation&gt;
  ForwardIterator2
    adjacent_difference(ExecutionPolicy&amp;&amp; exec,
                        ForwardIterator1 first, ForwardIterator1 last,
                        ForwardIterator2 result, BinaryOperation binary_op);
</pre>
<blockquote>
<p>
<ins>-?- Let <code>T</code> be the value type of <code>decltype(first)</code>. For the overloads that do not
take an argument <code>binary_op</code>, let <code>binary_op</code> be an lvalue that denotes an object of
type <code>const minus&lt;&gt;</code>.</ins>
</p><p>
-1- <i>Requires:</i>
<ol style="list-style-type: none">
<li><p>(1.1) &mdash; For the overloads with no <code>ExecutionPolicy</code>,
<del><code>InputIterator</code>’s value type</del> <ins><code>T</code></ins> shall be
<code>MoveAssignable</code> (Table 25) and shall be constructible from the type of <code>*first</code>.
<code>acc</code> (defined below) shall be writable (24.3.1 <a href="https://wg21.link/iterator.requirements.general">[iterator.requirements.general]</a>) to
the <code>result</code> output iterator. The result of the expression <del><code>val - std::move(acc)</code>
or</del> <code>binary_op(val, std::move(acc))</code> shall be writable to the <code>result</code> output
iterator.</p></li>

<li><p>(1.2) &mdash; For the overloads with an <code>ExecutionPolicy</code>, the <del>value type of
<code>ForwardIterator1</code> shall be <code>CopyConstructible</code> (Table 24), constructible from the
expression <code>*first - *first</code> or <code>binary_op(*first, *first)</code>, and assignable to the
value type of <code>ForwardIterator2</code></del><ins>result of the expressions
<code>binary_op(*first, *first)</code> and <code>*first</code> shall be writable to
<code>result</code></ins>.</p></li>

<li><p>(1.3) &mdash; [&hellip;]</p></li>
</ol>
<p/>
-2- <i>Effects:</i> For the overloads with no <code>ExecutionPolicy</code> and a non-empty range, the
function creates an accumulator <code>acc</code> <del>whose type is <code>InputIterator</code>’s value
type</del> <ins>of type <code>T</code></ins>, initializes it with <code>*first</code>, and assigns the
result to <code>*result</code>. For every iterator <code>i</code> in <code>[first + 1, last)</code> in order,
creates an object <code>val</code> whose type is <del><code>InputIterator</code>’s value type</del>
<ins><code>T</code></ins>, initializes it with <code>*i</code>, computes <del><code>val - std::move(acc)</code>
or</del> <code>binary_op(val, std::move(acc))</code>, assigns the result to
<code>*(result + (i - first))</code>, and move assigns from <code>val</code> to <code>acc</code>.
<p/>
-3- For the overloads with an <code>ExecutionPolicy</code> and a non-empty range, <del>first the function
creates an object whose type is <code>ForwardIterator1</code>'s value type, initializes it with
<code>*first</code>, and assigns the result to <code>*result</code>. Then for every <code>d</code> in
<code>[1, last - first - 1]</code>, creates an object <code>val</code> whose type is
<code>ForwardIterator1</code>'s value type, initializes it with <code>*(first + d) - *(first + d - 1)</code>
or <code>binary_op(*(first + d), *(first + d - 1))</code>, and assigns the result to
<code>*(result + d)</code></del><ins>performs <code>*result = *first</code>. Then, for every <code>d</code> in
<code>[1, last - first - 1]</code>, performs
<code>*(result + d) = binary_op(*(first + d), *(first + (d - 1)))</code></ins>.
</p>
</blockquote>
</blockquote>
</li>
</ol>
</blockquote>

<p><i>[2018-06 Rapperswil: Adopted]</i></p>



<p id="res-3058"><b>Proposed resolution:</b></p>
<p>This wording is relative to <a href="https://wg21.link/n4713">N4713</a>.</p>

<ol>
<li><p>Modify 26.10.12 <a href="https://wg21.link/adjacent.difference">[adjacent.difference]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;class InputIterator, class OutputIterator&gt;
  OutputIterator
    adjacent_difference(InputIterator first, InputIterator last, OutputIterator result);
template&lt;class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2&gt;
  ForwardIterator2
    adjacent_difference(ExecutionPolicy&amp;&amp; exec,
                        ForwardIterator1 first, ForwardIterator1 last, ForwardIterator2 result);

template&lt;class InputIterator, class OutputIterator, class BinaryOperation&gt;
  OutputIterator
    adjacent_difference(InputIterator first, InputIterator last,
                        OutputIterator result, BinaryOperation binary_op);
template&lt;class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2,
         class BinaryOperation&gt;
  ForwardIterator2
    adjacent_difference(ExecutionPolicy&amp;&amp; exec,
                        ForwardIterator1 first, ForwardIterator1 last,
                        ForwardIterator2 result, BinaryOperation binary_op);
</pre>
<blockquote>
<p>
<ins>-?- Let <code>T</code> be the value type of <code>decltype(first)</code>. For the overloads that do not
take an argument <code>binary_op</code>, let <code>binary_op</code> be an lvalue that denotes an object of
type <code>minus&lt;&gt;</code>.</ins>
</p><p>
-1- <i>Requires:</i>
<ol style="list-style-type: none">
<li><p>(1.1) &mdash; For the overloads with no <code>ExecutionPolicy</code>,
<del><code>InputIterator</code>’s value type</del> <ins><code>T</code></ins> shall be
<code>MoveAssignable</code> (Table 25) and shall be constructible from the type of <code>*first</code>.
<code>acc</code> (defined below) shall be writable (24.3.1 <a href="https://wg21.link/iterator.requirements.general">[iterator.requirements.general]</a>) to
the <code>result</code> output iterator. The result of the expression <del><code>val - std::move(acc)</code>
or</del> <code>binary_op(val, std::move(acc))</code> shall be writable to the <code>result</code> output
iterator.</p></li>

<li><p>(1.2) &mdash; For the overloads with an <code>ExecutionPolicy</code>, the <del>value type of
<code>ForwardIterator1</code> shall be <code>CopyConstructible</code> (Table 24), constructible from the
expression <code>*first - *first</code> or <code>binary_op(*first, *first)</code>, and assignable to the
value type of <code>ForwardIterator2</code></del><ins>result of the expressions
<code>binary_op(*first, *first)</code> and <code>*first</code> shall be writable to
<code>result</code></ins>.</p></li>

<li><p>(1.3) &mdash; [&hellip;]</p></li>
</ol>
<p/>
-2- <i>Effects:</i> For the overloads with no <code>ExecutionPolicy</code> and a non-empty range, the
function creates an accumulator <code>acc</code> <del>whose type is <code>InputIterator</code>’s value
type</del> <ins>of type <code>T</code></ins>, initializes it with <code>*first</code>, and assigns the
result to <code>*result</code>. For every iterator <code>i</code> in <code>[first + 1, last)</code> in order,
creates an object <code>val</code> whose type is <del><code>InputIterator</code>’s value type</del>
<ins><code>T</code></ins>, initializes it with <code>*i</code>, computes <del><code>val - std::move(acc)</code>
or</del> <code>binary_op(val, std::move(acc))</code>, assigns the result to
<code>*(result + (i - first))</code>, and move assigns from <code>val</code> to <code>acc</code>.
<p/>
-3- For the overloads with an <code>ExecutionPolicy</code> and a non-empty range, <del>first the function
creates an object whose type is <code>ForwardIterator1</code>'s value type, initializes it with
<code>*first</code>, and assigns the result to <code>*result</code>. Then for every <code>d</code> in
<code>[1, last - first - 1]</code>, creates an object <code>val</code> whose type is
<code>ForwardIterator1</code>'s value type, initializes it with <code>*(first + d) - *(first + d - 1)</code>
or <code>binary_op(*(first + d), *(first + d - 1))</code>, and assigns the result to
<code>*(result + d)</code></del><ins>performs <code>*result = *first</code>. Then, for every <code>d</code> in
<code>[1, last - first - 1]</code>, performs
<code>*(result + d) = binary_op(*(first + d), *(first + (d - 1)))</code></ins>.
</p>
</blockquote>
</blockquote>
</li>
</ol>





</body>
</html>
