Skip to content

Commit dac3b6c

Browse files
authored
Merge pull request #530 from tomaszkam/tk/reflect_multi_array
New issue: Multidimensional arrays are not supported by <tt>meta::ref…
2 parents e44d873 + c149fc6 commit dac3b6c

File tree

1 file changed

+111
-0
lines changed

1 file changed

+111
-0
lines changed

xml/issue4483.xml

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<?xml version='1.0' encoding='utf-8' standalone='no'?>
2+
<!DOCTYPE issue SYSTEM "lwg-issue.dtd">
3+
4+
<issue num="4483" status="New">
5+
<title>Multidimensional arrays are not supported by <tt>meta::reflect_constant_array</tt> and related functions</title>
6+
<section>
7+
<sref ref="[meta.define.static]"/>
8+
</section>
9+
<submitter>Tomasz Kamiński</submitter>
10+
<date>27 Nov 2025</date>
11+
<priority>99</priority>
12+
13+
<discussion>
14+
<p>As any array type (even of structural types) is not considered an structural type, per
15+
<sref ref="[temp.param]"/> p12, any invocation of `reflect_constant_array`/`define_static_array`
16+
with a multidimensional array or `span` of arrays is ill-formed due to the <i>Mandates</i> in
17+
<sref ref="[meta.define.static]"/> p8 that requires range value type to be structural.</p>
18+
19+
<p>As a consequence, `constant_of` currently supports only single-dimensional arrays
20+
(<tt>reflect_constant_array</tt> strips outermost extents), while multi-dimensional arrays are
21+
rejected.</p>
22+
23+
<p>Furthermore, `define_static_object` currently uses <tt>define_static_array(span(addressof(t), 1)).data()</tt>,
24+
for array types. Since for `T[N]` input this creates an multidimensional `T[1][N]` constant parameter
25+
object, this function does not support arrays at all. Creating a distinct template
26+
parameter object leads to emission of (otherwise unnecessary) additional symbols, and breaks the
27+
invariant that for all supported object types <tt>&amp;constant_of(o) == define_static_object(o)</tt>.
28+
We should use `reflect_constant_array` for arrays directly.</p>
29+
30+
<p>The <i>Throws</i> clause of `reflect_constant_array` was updated to include any exception
31+
thrown by iteration over range.</p>
32+
</discussion>
33+
34+
<resolution>
35+
<p>
36+
This wording is relative to <paper num="N5014"/> amended with changes from LWG <iref ref="4432"/>.
37+
</p>
38+
39+
<ol>
40+
41+
<li><p>Modify <sref ref="[meta.define.static]"/> as indicated:</p>
42+
43+
<pre>
44+
template&lt;ranges::input_range R&gt;
45+
consteval info reflect_constant_array(R&amp;&amp; r);
46+
</pre>
47+
<blockquote>
48+
<p>-8- Let <tt><del>T</del><ins>U</ins></tt> be <tt>ranges::range_value_t&lt;R&gt;</tt>
49+
and <ins><tt>T</tt> be <tt>remove_all_extents_&lt;U&gt;</tt></ins>
50+
<del><i>e<sub>i</sub></i> be <tt>static_cast&lt;T&gt;(*<i>it<sub>i</sub></i>)</tt>,
51+
where <i>it<sub>i</sub></i> is an iterator to the <i>i<sup>th</sup></i> element of `r`</del>.
52+
</p>
53+
<p>-9- <i>Mandates</i>:
54+
<ul style="list-style-type: none">
55+
<li><ins>(9.1) &mdash;</ins> <tt>T</tt> is a structural type (<sref ref="[temp.param]"/>),
56+
<del><tt>is_constructible_v&lt;T, ranges::range_reference_t&lt;R&gt;&gt;</tt> is `true`, and</del>
57+
</li>
58+
<li><ins>(9.2) &mdash;</ins> `T` satisfies `copy_constructible`<ins>, and</ins></li>
59+
<li><ins>(9.3) &mdash;</ins> if `U` is not an array type, then <tt>is_constructible_v&lt;T, ranges::range_reference_t&lt;R&gt;&gt;</tt> is `true`.</li>
60+
</ul>
61+
</p>
62+
<p>-10- Let `V` be the pack of values of type `info` of the same size as `r`,
63+
where the <i>i<sup>th</sup></i> element is
64+
<ul style="list-style-type: none">
65+
<li><ins>(10.1) &mdash; <tt>reflect_constant_array(*<i>it<sub>i</sub></i>)</tt> if <tt>U</tt> is an array type,</ins></li>
66+
<li><ins>(10.2) &mdash;</ins> <tt>reflect_constant(<ins>static_cast&lt;T&gt;(*<i>it<sub>i</sub></i>)</ins><del><i>e<sub>i</sub></i></del>)</tt><ins> otherwise,</ins></li>
67+
</ul>
68+
<ins>and <i>it<sub>i</sub></i> is an iterator to the <i>i<sup>th</sup></i> element of `r`</ins>.</p>
69+
<p>-11- Let <tt><i>P</i></tt> be
70+
<ul style="list-style-type: none">
71+
<li>(11.1) &mdash; If <tt>sizeof...(V) > 0</tt> is `true`, then the template parameter object (<sref ref="[temp.param]"/>) of type const `T[sizeof...(V)]`
72+
<del>initialized with `{[:V:]...}`</del><ins>, such that <tt>constant_of(<i>P</i>[<i>I</i>]) == V...[<i>I</i>]</tt> is `true`
73+
for all <tt><i>I</i></tt> in range [`0`, `sizeof...(V)`)</ins>.</li>
74+
<li>(11.2) &mdash; Otherwise, the template parameter object of type <tt>const array&lt;T, 0&gt;</tt> initialized with `{}`.</li>
75+
</ul></p>
76+
<p>-12- <i>Returns</i>: <tt>^^<i>P</i></tt>.</p>
77+
<p>-13- <i>Throws</i>:
78+
<ins>Any exception thrown by increment and dereference operations on iterator to `r` and comparison of such iterator to sentinel.</ins>
79+
Any exception thrown by the evaluation of any <ins>argument of `reflect_constant`.</ins><del><i>e<sub>i</sub></i>, or</del>
80+
`meta::exception` if evaluation of any <del><tt>reflect_constant(<i>e<sub>i</sub></i>)</tt></del><ins>evaluation of
81+
<tt>reflect_constant</tt> or <tt>reflect_constant_array</tt></ins> would exit via an exception.
82+
</p>
83+
</blockquote>
84+
[&hellip;]
85+
86+
<pre>
87+
template&lt;class T&gt;
88+
consteval const remove_cvref_t&lt;T&gt;* define_static_object(T&amp;&amp; t);
89+
</pre>
90+
<blockquote>
91+
<p>-15- <i>Effects</i>:Equivalent to:</p>
92+
<pre>
93+
using U = remove_cvref_t&lt;T&gt;;
94+
if constexpr (meta::is_class_type(^^U)) {
95+
return addressof(meta::extract&lt;const U&amp;&gt;(meta::reflect_constant(std::forward&lt;T&gt;(t))));
96+
<ins>} else if constexpr (meta::is_array_type(^^U)) {
97+
return addressof(meta::extract&lt;const U&amp;&gt;(meta::reflect_constant_array(std::forward&lt;T&gt;(t))));</ins>
98+
} else {
99+
return define_static_array(span(addressof(t), 1)).data();
100+
}
101+
</pre>
102+
</blockquote>
103+
104+
</li>
105+
</ol>
106+
107+
</resolution>
108+
109+
110+
111+
</issue>

0 commit comments

Comments
 (0)