Skip to content

Commit 1ae9907

Browse files
committed
New issue from Lénárd Szolnoki: "Constant expression ranges::size(r) Constraints and Mandates in [simd]"
1 parent 38ed885 commit 1ae9907

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed

xml/issue4409.xml

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
<?xml version='1.0' encoding='utf-8' standalone='no'?>
2+
<!DOCTYPE issue SYSTEM "lwg-issue.dtd">
3+
4+
<issue num="4409" status="New">
5+
<title>Constant expression `ranges::size(r)` <i>Constraints</i> and <i>Mandates</i> in [simd]</title>
6+
<section>
7+
<sref ref="[simd]"/>
8+
</section>
9+
<submitter>Lénárd Szolnoki</submitter>
10+
<date>10 Oct 2025</date>
11+
<priority>99</priority>
12+
13+
<discussion>
14+
<p>
15+
Various <i>Constraints</i> and <i>Mandates</i> in <sref ref="[simd]"/> are conditioned on `ranges::size(r)`,
16+
assuming that subsequent operations on the result are also constant expression. This is not a given,
17+
since `ranges::size(r)` is allowed to return an integer-class type, and it is not mandated that operations
18+
on integer-class types are usable in constant expressions.
19+
<p/>
20+
In particular:
21+
</p>
22+
<ol>
23+
<li><p>
24+
<sref ref="[simd.ctor]"/> p13:
25+
</p>
26+
<blockquote>
27+
<p>
28+
<i>Constraints</i>:
29+
</p>
30+
<ul>
31+
<li><p>`R` models `ranges::contiguous_range` and `ranges::sized_range`,</p></li>
32+
<li><p>`ranges::size(r)` is a constant expression, and</p></li>
33+
<li><p>`ranges::size(r)` is equal to `size()`.</p></li>
34+
</ul>
35+
</blockquote>
36+
<p>
37+
Here `ranges::size(r) == size()` might not be a constant expression, even when `ranges::size(r)`
38+
is. Operations that are not accounted for:
39+
</p>
40+
<ul>
41+
<li><p>Possible conversion from `range::size(r)` to <tt><i>simd-size-type</i></tt>.</p></li>
42+
<li><p>Possible operator overloading on ==.</p></li>
43+
</ul>
44+
</li>
45+
46+
<li><p>
47+
<sref ref="[simd.ctor]"/> p17+18:
48+
</p>
49+
<blockquote>
50+
<p>
51+
<i>Constraints</i>:
52+
</p>
53+
<ul>
54+
<li><p>`R` models `ranges::contiguous_range` and `ranges::sized_range`, and</p></li>
55+
<li><p>`ranges::size(r)` is a constant expression</p></li>
56+
</ul>
57+
<p>
58+
<i>Remarks:</i> The deduced type is equivalent to <tt>vec&lt;ranges::range_value_t&lt;R&gt;, ranges::size(r)&gt;</tt>.
59+
</p>
60+
</blockquote>
61+
<p>
62+
Here the second constraint is simply redundant, if failure to form the type is in the immediate context.
63+
If we want to type it out in the constraints then we should account for conversion to <tt><i>simd-size-type</i></tt>
64+
and narrowing.
65+
</p>
66+
</li>
67+
68+
<li><p>
69+
<sref ref="[simd.loadstore]"/> p2:
70+
</p>
71+
<blockquote>
72+
<p>
73+
<i>Mandates</i>: If `ranges::size(r)` is a constant expression then `ranges::size(r)` ≥ `V::size()`.
74+
</p>
75+
</blockquote>
76+
<p>
77+
Here <tt>ranges::size(r) &gt;= V::size()</tt> might not be a constant expression, even when
78+
`ranges::size(r)` is. It is unclear why a mathematical operator symbol is used here (and further
79+
down in the preconditions).
80+
</p>
81+
</li>
82+
</ol>
83+
84+
</discussion>
85+
86+
<resolution>
87+
<p>
88+
This wording is relative to <paper num="N5014"/>.
89+
</p>
90+
91+
<ol>
92+
93+
<li><p>Modify <sref ref="[simd.ctor]"/> as indicated:</p>
94+
95+
<blockquote>
96+
<pre>
97+
template&lt;class R, class... Flags&gt;
98+
constexpr basic_vec(R&amp;&amp; r, flags&lt;Flags...&gt; = {});
99+
template&lt;class R, class... Flags&gt;
100+
constexpr basic_vec(R&amp;&amp; r, const mask_type&amp; mask, flags&lt;Flags...&gt; = {});
101+
</pre>
102+
<blockquote>
103+
<p>
104+
-12- Let `mask` be `mask_type(true)` for the overload with no `mask` parameter.
105+
<p/>
106+
-13- <i>Constraints</i>:
107+
</p>
108+
<ol style="list-style-type: none">
109+
<li><p>
110+
(13.1) &mdash; `R` models `ranges::contiguous_range` and `ranges::sized_range`, <ins>and</ins>
111+
</p></li>
112+
<li><p>
113+
(13.2) &mdash; <tt>ranges::size(r) <ins>== size()</ins></tt> is a constant expression, and <ins>evaluates to `true`.</ins>
114+
</p></li>
115+
<li><p>
116+
<del>(13.3) &mdash; `ranges::size(r)` is equal to `size()`.</del>
117+
</p></li>
118+
</ol>
119+
[&hellip;]
120+
</blockquote>
121+
<pre>
122+
template&lt;class R, class... Ts&gt;
123+
basic_vec(R&amp;&amp; r, Ts...) -&gt; <i>see below</i>;
124+
</pre>
125+
<blockquote>
126+
<p>
127+
-17- <i>Constraints</i>:
128+
</p>
129+
<ol style="list-style-type: none">
130+
<li><p>
131+
<del>(17.1) &mdash;</del> `R` models `ranges::contiguous_range` and `ranges::sized_range`<del>, and</del><ins>.</ins>
132+
</p></li>
133+
<li><p>
134+
<del>(17.2) &mdash; `ranges::size(r)` is a constant expression.</del>
135+
</p></li>
136+
</ol>
137+
<p>
138+
-18- <i>Remarks</i>: The deduced type is equivalent to <tt>vec&lt;ranges::range_value_t&lt;R&gt;, ranges::size(r)&gt;</tt>.
139+
</p>
140+
</blockquote>
141+
</blockquote>
142+
</li>
143+
144+
<li><p>Modify <sref ref="[simd.loadstore]"/> as indicated:</p>
145+
146+
<blockquote>
147+
<pre>
148+
template&lt;class V = <i>see below</i>, ranges::contiguous_range R, class... Flags&gt;
149+
requires ranges::sized_range&lt;R&gt;
150+
constexpr V unchecked_load(R&amp;&amp; r, flags&lt;Flags...&gt; f = {});
151+
[&hellip;]
152+
template&lt;class V = <i>see below</i>, contiguous_iterator I, sized_sentinel_for&lt;I&gt; S, class... Flags&gt;
153+
constexpr V unchecked_load(I first, S last, const typename V::mask_type&amp; mask,
154+
flags&lt;Flags...&gt; f = {});
155+
</pre>
156+
<blockquote>
157+
<p>
158+
-1- Let [&hellip;]
159+
<p/>
160+
-2- <i>Mandates</i>: If <tt>ranges::size(r) <ins>&gt;= V::size()</ins></tt> is a constant expression
161+
then <del>`ranges::size(r)` ≥ `V::size()`</del><ins>it evaluates to `true`</ins>.
162+
</p>
163+
</blockquote>
164+
</blockquote>
165+
</li>
166+
167+
</ol>
168+
169+
</resolution>
170+
171+
</issue>

0 commit comments

Comments
 (0)