Skip to content

Commit 82796b0

Browse files
committed
New issue from Ruslan Arutyunyan: "Parallel std::ranges::destroy should allow exceptions"
1 parent 18fbb0e commit 82796b0

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed

xml/issue4431.xml

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<?xml version='1.0' encoding='utf-8' standalone='no'?>
2+
<!DOCTYPE issue SYSTEM "lwg-issue.dtd">
3+
4+
<issue num="4431" status="New">
5+
<title>Parallel `std::ranges::destroy` should allow exceptions</title>
6+
<section>
7+
<sref ref="[memory.syn]"/>
8+
</section>
9+
<submitter>Ruslan Arutyunyan</submitter>
10+
<date>24 Oct 2025</date>
11+
<priority>99</priority>
12+
13+
<discussion>
14+
<p>
15+
The serial `std::ranges::destroy` algorithm is marked as `noexcept`. However, the parallel
16+
counterpart should not be marked `noexcept`.
17+
<p/>
18+
While we generally don't expect any exceptions from the `destroy` algorithm when called
19+
with the standard execution policies (`seq`, `unseq`, `par`, `par_unseq`), the
20+
implementation-defined policies for parallel algorithms are allowed by the C++ standard,
21+
and it is up to the particular execution policy to decide which exceptions can be thrown
22+
from parallel algorithms.
23+
</p>
24+
</discussion>
25+
26+
<resolution>
27+
<p>
28+
This wording is relative to <paper num="N5014"/>.
29+
</p>
30+
31+
<ol>
32+
33+
<li><p>Modify <sref ref="[memory.syn]"/>, header <tt>&lt;memory&gt;</tt> synopsis, as indicated:</p>
34+
35+
<blockquote class="note">
36+
<p>
37+
[<i>Drafting note</i>: There are no further prototype definitions for the affected
38+
<tt><i>execution-policy</i></tt> overloads in <sref ref="[specialized.destroy]"/>.]
39+
</p>
40+
</blockquote>
41+
42+
<blockquote>
43+
<pre>
44+
[&hellip;]
45+
<i>// 26.11.9, <sref ref="[specialized.destroy]"/></i>
46+
template&lt;class T&gt;
47+
constexpr void destroy_at(T* location); <i>// freestanding</i>
48+
template&lt;class NoThrowForwardIterator&gt;
49+
constexpr void destroy(NoThrowForwardIterator first, <i>// freestanding</i>
50+
NoThrowForwardIterator last);
51+
template&lt;class ExecutionPolicy, class NoThrowForwardIterator&gt;
52+
void destroy(ExecutionPolicy&amp;&amp; exec, <i>// freestanding-deleted,</i>
53+
NoThrowForwardIterator first, <i>// see <sref ref="[algorithms.parallel.overloads]"/></i>
54+
NoThrowForwardIterator last);
55+
template&lt;class NoThrowForwardIterator, class Size&gt;
56+
constexpr NoThrowForwardIterator destroy_n(NoThrowForwardIterator first, <i>// freestanding</i>
57+
Size n);
58+
template&lt;class ExecutionPolicy, class NoThrowForwardIterator, class Size&gt;
59+
NoThrowForwardIterator destroy_n(ExecutionPolicy&amp;&amp; exec, <i>// freestanding-deleted,</i>
60+
NoThrowForwardIterator first, Size n); <i>// see <sref ref="[algorithms.parallel.overloads]"/></i>
61+
namespace ranges {
62+
template&lt;destructible T&gt;
63+
constexpr void destroy_at(T* location) noexcept; <i>// freestanding</i>
64+
65+
template&lt;<i>nothrow-input-iterator</i> I, <i>nothrow-sentinel-for</i> &lt;I&gt; S&gt;
66+
requires destructible&lt;iter_value_t&lt;I&gt;&gt;
67+
constexpr I destroy(I first, S last) noexcept; <i>// freestanding</i>
68+
template&lt;<i>nothrow-input-range</i> R&gt;
69+
requires destructible&lt;range_value_t&lt;R&gt;&gt;
70+
constexpr borrowed_iterator_t&lt;R&gt; destroy(R&amp;&amp; r) noexcept; <i>// freestanding</i>
71+
72+
template&lt;<i>nothrow-input-iterator</i> I&gt;
73+
requires destructible&lt;iter_value_t&lt;I&gt;&gt;
74+
constexpr I destroy_n(I first, iter_difference_t&lt;I&gt; n) noexcept; <i>// freestanding</i>
75+
76+
template&lt;<i>execution-policy</i> Ep, <i>nothrow-random-access-iterator</i> I,
77+
<i>nothrow-sized-sentinel-for</i> &lt;I&gt; S&gt;
78+
requires destructible&lt;iter_value_t&lt;I&gt;&gt;
79+
I destroy(Ep&amp;&amp; exec, I first, S last) <del>noexcept</del>; <i>// freestanding-deleted,</i>
80+
<i>// see <sref ref="[algorithms.parallel.overloads]"/></i>
81+
template&lt;<i>execution-policy</i> Ep, <i>nothrow-sized-random-access-range</i> R&gt;
82+
requires destructible&lt;range_value_t&lt;R&gt;&gt;
83+
borrowed_iterator_t&lt;R&gt; destroy(Ep&amp;&amp; exec, R&amp;&amp; r) <del>noexcept</del>; <i>// freestanding-deleted,</i>
84+
<i>// see <sref ref="[algorithms.parallel.overloads]"/></i>
85+
template&lt;<i>execution-policy</i> Ep, <i>nothrow-random-access-iterator</i> I&gt;
86+
requires destructible&lt;iter_value_t&lt;I&gt;&gt;
87+
I destroy_n(Ep&amp;&amp; exec, I first, iter_difference_t&lt;I&gt; n) <del>noexcept</del>; <i>// freestanding-deleted,</i>
88+
<i>// see <sref ref="[algorithms.parallel.overloads]"/></i>
89+
}
90+
[&hellip;]
91+
</pre>
92+
</blockquote>
93+
</li>
94+
95+
</ol>
96+
97+
</resolution>
98+
99+
</issue>

0 commit comments

Comments
 (0)