Skip to content

Commit 146db26

Browse files
committed
New issue from Hewill: "join_view should be sized_range when applied to ranges of simd::vec"
1 parent d046e8b commit 146db26

File tree

1 file changed

+157
-0
lines changed

1 file changed

+157
-0
lines changed

xml/issue4401.xml

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
<?xml version='1.0' encoding='utf-8' standalone='no'?>
2+
<!DOCTYPE issue SYSTEM "lwg-issue.dtd">
3+
4+
<issue num="4401" status="New">
5+
<title>`join_view` should be `sized_range` when applied to ranges of `simd::vec`</title>
6+
<section>
7+
<sref ref="[range.join.view]"/>
8+
<sref ref="[range.join.with.view]"/>
9+
<sref ref="[range.lazy.split.view]"/>
10+
</section>
11+
<submitter>Hewill Kang</submitter>
12+
<date>02 Oct 2025</date>
13+
<priority>99</priority>
14+
15+
<discussion>
16+
<p>
17+
Consider:
18+
<p/>
19+
Collecting a `simd::vec` into a `vector` for output is a common use case. <paper num="P3480R6"/>
20+
makes `simd::vec` a range so we can simply flatten it with `views::join` (original example from
21+
the paper):
22+
</p>
23+
<blockquote><pre>
24+
std::vector&lt;std::simd::vec&lt;float&gt;&gt; data;
25+
auto range_of_float = data | std::views::join;
26+
</pre></blockquote>
27+
<p>
28+
In this case, it makes sense for `join_view` to be `sized_range` because `simd::vec::size()`
29+
is a constant expression that can be multiplied by the original `vector` size to get the
30+
result size of the `join_view`.
31+
<p/>
32+
In <code>&lt;ranges&gt;</code>, we use the <code><i>tiny-range</i></code> concept
33+
to consider types that can obtain static sizes specifically, and `simd::vec`
34+
seems to be a good fit.
35+
</p>
36+
</discussion>
37+
38+
<resolution>
39+
<p>
40+
This wording is relative to <paper num="N5014"/>.
41+
</p>
42+
43+
<ol>
44+
45+
<li><p>Modify <sref ref="[range.join.view]"/> as indicated:</p>
46+
47+
<blockquote class="note">
48+
<p>
49+
[<i>Drafting note:</i> The proposed wording follows the <code><i>tiny-range</i></code>'s way to check if
50+
`R::size()` is a constant expression instead of further checking `ranges::size(r)` for simplicity.]
51+
</p>
52+
</blockquote>
53+
54+
<blockquote>
55+
<pre>
56+
namespace std::ranges {
57+
<ins>template&lt;auto&gt; struct <i>require-constant</i>; // <i>exposition only</i>
58+
59+
template&lt;class R&gt;
60+
concept <i>static-sized-range</i> = // <i>exposition only</i>
61+
sized_range&lt;R&gt; &amp;&amp;
62+
requires { typename <i>require-constant</i>&lt;remove_reference_t&lt;R&gt;::size()&gt;; };</ins>
63+
64+
template&lt;input_range V&gt;
65+
requires view&lt;V&gt; &amp;&amp; input_range&lt;range_reference_t&lt;V&gt;&gt;&gt;
66+
class join_view : public view_interface&lt;join_view&lt;V&gt;&gt; {
67+
[&hellip;]
68+
public:
69+
[&hellip;]
70+
<ins>constexpr auto size()
71+
requires sized_range&lt;V&gt; &amp;&amp; <i>static-sized-range</i>&lt;<i>InnerRng</i>&gt; {
72+
using CT = common_type_t&lt;range_size_t&lt;V&gt;, range_size_t&lt;<i>InnerRng</i>&gt;&gt;;
73+
return CT(ranges::size(<i>base_</i>)) * CT(remove_reference_t&lt;<i>InnerRng</i>&gt;::size());
74+
}
75+
76+
constexpr auto size() const
77+
requires sized_range&lt;const V&gt; &amp;&amp;
78+
<i>static-sized-range</i>&lt;range_reference_t&lt;const V&gt;&gt; {
79+
using <i>InnerConstRng</i> = range_reference_t&lt;const V&gt;;
80+
using CT = common_type_t&lt;range_size_t&lt;V&gt;, range_size_t&lt;<i>InnerConstRng</i>&gt;&gt;;
81+
return CT(ranges::size(<i>base_</i>)) * CT(remove_reference_t&lt;<i>InnerConstRng</i>&gt;::size());
82+
}</ins>
83+
};
84+
[&hellip;]
85+
}
86+
</pre>
87+
</blockquote>
88+
</li>
89+
90+
<li><p>Modify <sref ref="[range.join.with.view]"/> as indicated:</p>
91+
92+
<blockquote>
93+
<pre>
94+
namespace std::ranges {
95+
[&hellip;]
96+
template&lt;input_range V, forward_range Pattern&gt;
97+
requires view&lt;V&gt; &amp;&amp; input_range&lt;range_reference_t&lt;V&gt;&gt;
98+
&amp;&amp; view&lt;Pattern&gt;
99+
&amp;&amp; <i>concatable</i>&lt;range_reference_t&lt;V&gt;, Pattern&gt;
100+
class join_with_view : public view_interface&lt;join_with_view&lt;V, Pattern&gt;&gt; {
101+
[&hellip;]
102+
public:
103+
[&hellip;]
104+
<ins>constexpr auto size()
105+
requires sized_range&lt;V&gt; &amp;&amp; sized_range&lt;Pattern&gt; &amp;&amp;
106+
<i>static-sized-range</i>&lt;<i>InnerRng</i>&gt; {
107+
using CT = common_type_t&lt;
108+
range_size_t&lt;V&gt;, range_size_t&lt;<i>InnerRng</i>&gt;, range_size_t&lt;Pattern&gt;&gt;;
109+
const auto base_size = ranges::size(<i>base_</i>);
110+
if (base_size == 0)
111+
return CT(0);
112+
return CT(base_size) * CT(remove_reference_t&lt;<i>InnerRng</i>&gt;::size()) +
113+
CT(base_size - 1) * CT(ranges::size(<i>pattern_</i>));
114+
}
115+
116+
constexpr auto size() const
117+
requires sized_range&lt;const V&gt; &amp;&amp; sized_range&lt;const Pattern&gt; &amp;&amp;
118+
<i>static-sized-range</i>&lt;range_reference_t&lt;const V&gt;&gt; {
119+
using <i>InnerConstRng</i> = range_reference_t&lt;const V&gt;;
120+
using CT = common_type_t&lt;
121+
range_size_t&lt;const V&gt;, range_size_t&lt;<i>InnerConstRng</i>&gt;, range_size_t&lt;const Pattern&gt;&gt;;
122+
const auto base_size = ranges::size(<i>base_</i>);
123+
if (base_size == 0)
124+
return CT(0);
125+
return CT(base_size) * CT(remove_reference_t&lt;<i>InnerConstRng</i>&gt;::size()) +
126+
CT(base_size - 1) * CT(ranges::size(<i>pattern_</i>));
127+
}</ins>
128+
};
129+
[&hellip;]
130+
}
131+
</pre>
132+
</blockquote>
133+
</li>
134+
135+
<li><p>Modify <sref ref="[range.lazy.split.view]"/> as indicated:</p>
136+
137+
<blockquote>
138+
<pre>
139+
namespace std::ranges {
140+
<del>template&lt;auto&gt; struct <i>require-constant</i>; // <i>exposition only</i></del>
141+
142+
template&lt;class R&gt;
143+
concept <i>tiny-range</i> = // <i>exposition only</i>
144+
<ins><i>static-sized-range</i>&lt;R&gt;</ins><del>sized_range&lt;R&gt; &amp;&amp;
145+
requires { typename <i>require-constant</i>&lt;remove_reference_t&lt;R&gt;::size()&gt;; }</del> &amp;&amp;
146+
(remove_reference_t&lt;R&gt;::size() &lt;= 1);
147+
148+
[&hellip;]
149+
}
150+
</pre>
151+
</blockquote>
152+
</li>
153+
</ol>
154+
155+
</resolution>
156+
157+
</issue>

0 commit comments

Comments
 (0)