<div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">---------- Forwarded message ---------<br>From: <strong class="gmail_sendername" dir="auto">Marcin Jaczewski</strong> <span dir="auto">&lt;<a href="mailto:marcinjaczewski86@gmail.com">marcinjaczewski86@gmail.com</a>&gt;</span><br>Date: Fri, Mar 4, 2022 at 3:06 PM<br>Subject: Re: [std-proposals] A new kind variable for immediate functions<br>To: Torben Thaysen &lt;<a href="mailto:thaysentorben@gmail.com">thaysentorben@gmail.com</a>&gt;<br>Cc: Marcin Jaczewski &lt;<a href="mailto:marcinjaczewski86@gmail.com">marcinjaczewski86@gmail.com</a>&gt;<br></div><br><br>pt., 4 mar 2022 o 14:53 Torben Thaysen &lt;<a href="mailto:thaysentorben@gmail.com" target="_blank">thaysentorben@gmail.com</a>&gt; napisał(a):<br>
&gt;&gt;<br>
&gt;&gt; I think this should be fixed a bit diffrent way. Current `constexpr`<br>
&gt;&gt; variables can materialize in result code and this is problem if we use<br>
&gt;&gt; memory allocation.<br>
&gt;<br>
&gt; I am not sure what you mean. The way I understand it, whether you find some trace of constexpr variables in the final binary/assembly<br>
&gt; (or whether they are &quot;materialized&quot;) is decided by the compiler the same way as for any other (inline) variable. Since what I am proposing is<br>
&gt; a local variable inside of immediate functions, the only place they could &quot;materialize&quot; is into the body of that function, which by definition doesn&#39;t<br>
&gt; exist at runtime.<br>
&gt; When you try something like<br>
&gt;<br>
&gt; consteval const int* leak_ptr() {<br>
&gt;     consteval int i = 1;<br>
&gt;     return &amp;i;<br>
&gt; }<br>
&gt; int main() {<br>
&gt;     constexpr auto ptr = leak_ptr();<br>
&gt; }<br>
&gt;<br>
&gt; the local variable won&#39;t &quot;materialize&quot;, instead you would get a compiler error since a pointer to an object of automatic storage duration is not<br>
&gt; allowed in a constant expression.<br>
&gt;<br>
I mean case like:<br>
```<br>
int main()<br>
{<br>
    constexpr auto i = 5;<br>
<br>
    return (unsigned long int)&amp;i;<br>
}<br>
```<br>
<a href="https://godbolt.org/z/Wx1v5KWjo" rel="noreferrer" target="_blank">https://godbolt.org/z/Wx1v5KWjo</a><br>
We have a real variable on stack with address.<br>
This means we can&#39;t use `std::string` as it would &quot;leak&quot; memory from<br>
compile time to run time and mixup life times of compilation and<br>
runtime.<br>
Most of the limitations of `constexpr` is because of this case.<br>
<br>
<br>
&gt;&gt; One way I could see to fix it make option for &quot;pure&quot; `constexpr<br>
&gt;&gt; variables that only live during compilation and are not accessible in<br>
&gt;&gt; anyway by run time.<br>
&gt;<br>
&gt; This sounds quite similar to what I proposed but with the requirement to be in an immediate function removed. This might have the advantage<br>
&gt; that it could save you from having to define an extra function. However consider that with your version you are restricted to the initializer of result<br>
&gt; variable, which means that when the constructor you mentioned doesn&#39;t exist or you want to do something more complicated the just copy some data,<br>
&gt; you would have to write a helper function anyways.<br>
&gt;<br>
<br>
Yes, but the difference is I make a clear distinction between what<br>
lives at compile time and what lives at runtime. as now `constexpr`<br>
variables can migrate between.<br>
<br>
&gt; Marcin Jaczewski &lt;<a href="mailto:marcinjaczewski86@gmail.com" target="_blank">marcinjaczewski86@gmail.com</a>&gt;:<br>
&gt;&gt;<br>
&gt;&gt; pt., 4 mar 2022 o 12:54 Torben Thaysen via Std-Proposals<br>
&gt;&gt; &lt;<a href="mailto:std-proposals@lists.isocpp.org" target="_blank">std-proposals@lists.isocpp.org</a>&gt; napisał(a):<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; Currently when computing things at compile time one sometimes faces a problem when trying to output the result to a constexpr variable.<br>
&gt;&gt; &gt; This happens when the result is data structure without a fixed size that utilizes dynamic memory allocation, which in itself is not a<br>
&gt;&gt; &gt; constant expression (for example a vector). Today the result can be converted to a more appropriate fixed sized structure like this:<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; constexpr std::vector&lt;int&gt; compute_vector();<br>
&gt;&gt; &gt; constexpr std::size_t extract_size() { return compute_vector().size(); }<br>
&gt;&gt; &gt; constexpr auto as_array() {<br>
&gt;&gt; &gt;     auto vec = compute_vector();<br>
&gt;&gt; &gt;     std::array&lt;int, extract_size()&gt; arr;<br>
&gt;&gt; &gt;     std::copy(vec.begin(), vec.end(), arr.begin());<br>
&gt;&gt; &gt;     return arr;<br>
&gt;&gt; &gt; }<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; But this somewhat awkwardly involves doing the computation twice. The only way around this is to copy the data to a large intermediate array<br>
&gt;&gt; &gt; then copy it again into an array of the right size. Neither of these solutions is really ideal and that is what this proposal aims to solve.<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; For this I want to introduce a new kind of variable that can be declared inside an immediate function. With this the above example could look like:<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; constexpr std::vector&lt;int&gt; compute_vector();<br>
&gt;&gt; &gt; consteval auto as_array() {<br>
&gt;&gt; &gt;     consteval auto vec = compute_vector(); // example syntax<br>
&gt;&gt; &gt;     std::array&lt;int, vec.size()&gt; arr;<br>
&gt;&gt; &gt;     std::copy(vec.begin(), vec.end(), arr.begin());<br>
&gt;&gt; &gt;     return arr;<br>
&gt;&gt; &gt; }<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; The requirements for this type of variable should conceptually be similar to those for constexpr variables (see 9.2.6.10 and 7.7.11) except that:<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; Targets of pointers and references don&#39;t have to have static storage duration. In particular pointers to dynamically allocated memory are allowed.<br>
&gt;&gt; &gt; Memory allocations performed in the initialization can (and must) be deallocated in the destructor.<br>
&gt;&gt; &gt; And (i think) pointers to immediate functions can also be allowed, since this type of variable only exists inside immediate functions. Although this<br>
&gt;&gt; &gt; isn&#39;t required for the aim of this proposal.<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; To my reading this lifts all the requirements of 7.7.11 so that any core constant expression with the modified allocation requirement would be allowed.<br>
&gt;&gt; &gt; Like with constexpr variables these new variables should also be implied to be const. And I propose for consistency they should be allowed to be<br>
&gt;&gt; &gt; declared in any immediate function context as by 7.7.13 (i.e. also inside a if consteval statement).<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; Looking forward to your feedback<br>
&gt;&gt; &gt; Torben<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; --<br>
&gt;&gt; &gt; Std-Proposals mailing list<br>
&gt;&gt; &gt; <a href="mailto:Std-Proposals@lists.isocpp.org" target="_blank">Std-Proposals@lists.isocpp.org</a><br>
&gt;&gt; &gt; <a href="https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals" rel="noreferrer" target="_blank">https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals</a><br>
&gt;&gt;<br>
&gt;&gt; I think this should be fixed a bit diffrent way. Current `constexpr`<br>
&gt;&gt; variables can materialize in result code and this is problem if we use<br>
&gt;&gt; memory allocation.<br>
&gt;&gt; One way I could see to fix it make option for &quot;pure&quot; `constexpr<br>
&gt;&gt; variables that only live during compilation and are not accessible in<br>
&gt;&gt; anyway by run time.<br>
&gt;&gt; This way we could make:<br>
&gt;&gt; ```<br>
&gt;&gt; int main() //can be used in any function!<br>
&gt;&gt; {<br>
&gt;&gt;     consteval auto s1 = std::string(&quot;Test&quot;); //variable and memory<br>
&gt;&gt; allocation live only during &quot;compilation&quot; of `main`, we could consider<br>
&gt;&gt; this a new `static` in some way.<br>
&gt;&gt;     static constexpr std::array&lt;int, s1.size()&gt; a1 = { s1.begin(),<br>
&gt;&gt; s1.end() }; //assume that array have constructor that can copy from<br>
&gt;&gt; range<br>
&gt;&gt;<br>
&gt;&gt;     auto s2 = std::string(s1); //Error! `s1` is not accessible here!<br>
&gt;&gt;     auto s3 = std::string(a1.begin(), a1.end()); //normal string that<br>
&gt;&gt; copy data from static memory<br>
&gt;&gt; }<br>
&gt;&gt; ```<br>
</div></div>

