Skip to content

Commit

Permalink
A little more exposition
Browse files Browse the repository at this point in the history
  • Loading branch information
brevzin committed Nov 13, 2024
1 parent 0112cff commit a55dcaf
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 35 deletions.
19 changes: 19 additions & 0 deletions 3496_immediate_escalating/immediate-escalating.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,25 @@ Here also, the call to `id(x)` internally isn't a constant expression, but `A(42

Change the rules around what constitutes an immediate-escalating expression such that we only consider a consteval call to "bubble up" if it isn't already enclosed in a constant expression.

Examining the original example in the context of the terms that this paper will introduce/adjust in the wording:

::: std
```cpp
constexpr int f2() {
return enumerators_of(^E).size();
}
```
:::

In the expression `enumerators_of(^E).size()` (which is not in an immediate function context):

* `enumerators_of` is a consteval-only expression (because it names an immediate function)
* `^E` will also be a consteval-only expression (because it has consteval-only type)
* the call expression `enumerators_of(^E)` is a consteval-only expression (because it has an immediate subexpression that is consteval-only). It is not an immediate invocation because it is not a constant expression.
* the larger expression `enumerators_of(^E).size()` _is_ a constant expression, has a non-constant subexpression that is consteval-only, and is thus an immediate invocation. This makes `enumerators_of(^E)` no longer an immediate-escalating expression (which it is in the status quo).

The intent of this proposal is that it is a DR against [@P2564R3].

## Implementation Experience

Thanks to Jason Merrill for implementing this proposal, suggesting I split it off from [@P3032R2], and giving wording help.
Expand Down
98 changes: 63 additions & 35 deletions 3496_immediate_escalating/p3496r0.html
Original file line number Diff line number Diff line change
Expand Up @@ -699,6 +699,34 @@ <h1 data-number="2" style="border-bottom:1px solid #cccccc" id="proposal"><span
<p>Change the rules around what constitutes an immediate-escalating
expression such that we only consider a consteval call to “bubble up” if
it isn’t already enclosed in a constant expression.</p>
<p>Examining the original example in the context of the terms that this
paper will introduce/adjust in the wording:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> <span class="dt">int</span> f2<span class="op">()</span> <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> enumerators_of<span class="op">(^</span>E<span class="op">).</span>size<span class="op">()</span>;</span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
</div>
<p>In the expression <code class="sourceCode cpp">enumerators_of<span class="op">(^</span>E<span class="op">).</span>size<span class="op">()</span></code>
(which is not in an immediate function context):</p>
<ul>
<li><code class="sourceCode cpp">enumerators_of</code> is a
consteval-only expression (because it names an immediate function)</li>
<li><code class="sourceCode cpp"><span class="op">^</span>E</code> will
also be a consteval-only expression (because it has consteval-only
type)</li>
<li>the call expression <code class="sourceCode cpp">enumerators_of<span class="op">(^</span>E<span class="op">)</span></code>
is a consteval-only expression (because it has an immediate
subexpression that is consteval-only). It is not an immediate invocation
because it is not a constant expression.</li>
<li>the larger expression <code class="sourceCode cpp">enumerators_of<span class="op">(^</span>E<span class="op">).</span>size<span class="op">()</span></code>
<em>is</em> a constant expression, has a non-constant subexpression that
is consteval-only, and is thus an immediate invocation. This makes <code class="sourceCode cpp">enumerators_of<span class="op">(^</span>E<span class="op">)</span></code>
no longer an immediate-escalating expression (which it is in the status
quo).</li>
</ul>
<p>The intent of this proposal is that it is a DR against <span class="citation" data-cites="P2564R3">[<a href="https://wg21.link/p2564r3" role="doc-biblioref">P2564R3</a>]</span>.</p>
<h2 data-number="2.1" id="implementation-experience"><span class="header-section-number">2.1</span> Implementation Experience<a href="#implementation-experience" class="self-link"></a></h2>
<p>Thanks to Jason Merrill for implementing this proposal, suggesting I
split it off from <span class="citation" data-cites="P3032R2">[<a href="https://wg21.link/p3032r2" role="doc-biblioref">P3032R2</a>]</span>, and giving wording help.</p>
Expand All @@ -707,10 +735,10 @@ <h2 data-number="2.1" id="implementation-experience"><span class="header-section
example</a> brought up during the implementation of <span class="citation" data-cites="P2564R3">[<a href="https://wg21.link/p2564r3" role="doc-biblioref">P2564R3</a>]</span>:</p>
<div class="std">
<blockquote>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">int</span> g<span class="op">(</span><span class="dt">int</span> p<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> p; <span class="op">}</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">constexpr</span> <span class="kw">auto</span> f<span class="op">(</span>T<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> g; <span class="op">}</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> r <span class="op">=</span> f<span class="op">(</span><span class="dv">1</span><span class="op">)(</span><span class="dv">2</span><span class="op">)</span>;</span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> s <span class="op">=</span> f<span class="op">(</span><span class="dv">1</span><span class="op">)(</span><span class="dv">2</span><span class="op">)</span> <span class="op">+</span> r;</span></code></pre></div>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">consteval</span> <span class="dt">int</span> g<span class="op">(</span><span class="dt">int</span> p<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> p; <span class="op">}</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">typename</span> T<span class="op">&gt;</span> <span class="kw">constexpr</span> <span class="kw">auto</span> f<span class="op">(</span>T<span class="op">)</span> <span class="op">{</span> <span class="cf">return</span> g; <span class="op">}</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> r <span class="op">=</span> f<span class="op">(</span><span class="dv">1</span><span class="op">)(</span><span class="dv">2</span><span class="op">)</span>;</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> s <span class="op">=</span> f<span class="op">(</span><span class="dv">1</span><span class="op">)(</span><span class="dv">2</span><span class="op">)</span> <span class="op">+</span> r;</span></code></pre></div>
</blockquote>
</div>
<p>Under the original C++20 rules, <code class="sourceCode cpp">f<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span></code>
Expand Down Expand Up @@ -804,35 +832,35 @@ <h2 data-number="2.2" id="wording"><span class="header-section-number">2.2</span
<div class="example9">
<span><em>Example 9:</em> </span>
<div>
<div class="sourceCode" id="cb5"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a> struct A {</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a> int x;</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a> int y = id(x);</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> };</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a> template&lt;class T&gt;</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a> constexpr int k(int) { // k&lt;int&gt; is not an immediate function because A(42) is a</span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a> return A(42).y; // constant expression and thus not immediate-escalating</span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a> }</span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a><span class="va">+ struct unique_ptr {</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true" tabindex="-1"></a><span class="va">+ int* p;</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true" tabindex="-1"></a><span class="va">+ constexpr unique_ptr(int i) : p(new int(i)) { }</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true" tabindex="-1"></a><span class="va">+ constexpr ~unique_ptr() { delete p; }</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true" tabindex="-1"></a><span class="va">+ constexpr int deref() const { return *p; }</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true" tabindex="-1"></a><span class="va">+ };</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true" tabindex="-1"></a><span class="va">+ consteval unique_ptr make_unique(int i) {</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true" tabindex="-1"></a><span class="va">+ return unique_ptr(i);</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true" tabindex="-1"></a><span class="va">+ }</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true" tabindex="-1"></a><span class="va">+ constexpr int overly_complicated() {</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true" tabindex="-1"></a><span class="va">+ return make_unique(121).deref(); // OK, make_unique(121) is consteval-only but it is not</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true" tabindex="-1"></a><span class="va">+ // immediate-escalating because make_unique(121).deref()</span></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true" tabindex="-1"></a><span class="va">+ // is a constant expression and thus an immediate invocation.</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true" tabindex="-1"></a><span class="va">+ }</span></span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true" tabindex="-1"></a><span class="va">+ static_assert(overly_complicated() == 121);</span></span></code></pre></div>
<div class="sourceCode" id="cb6"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a> struct A {</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a> int x;</span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a> int y = id(x);</span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a> };</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a> template&lt;class T&gt;</span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true" tabindex="-1"></a> constexpr int k(int) { // k&lt;int&gt; is not an immediate function because A(42) is a</span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true" tabindex="-1"></a> return A(42).y; // constant expression and thus not immediate-escalating</span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true" tabindex="-1"></a> }</span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true" tabindex="-1"></a><span class="va">+ struct unique_ptr {</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true" tabindex="-1"></a><span class="va">+ int* p;</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true" tabindex="-1"></a><span class="va">+ constexpr unique_ptr(int i) : p(new int(i)) { }</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true" tabindex="-1"></a><span class="va">+ constexpr ~unique_ptr() { delete p; }</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true" tabindex="-1"></a><span class="va">+ constexpr int deref() const { return *p; }</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true" tabindex="-1"></a><span class="va">+ };</span></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true" tabindex="-1"></a><span class="va">+ consteval unique_ptr make_unique(int i) {</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true" tabindex="-1"></a><span class="va">+ return unique_ptr(i);</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true" tabindex="-1"></a><span class="va">+ }</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true" tabindex="-1"></a><span class="va">+ constexpr int overly_complicated() {</span></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true" tabindex="-1"></a><span class="va">+ return make_unique(121).deref(); // OK, make_unique(121) is consteval-only but it is not</span></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true" tabindex="-1"></a><span class="va">+ // immediate-escalating because make_unique(121).deref()</span></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true" tabindex="-1"></a><span class="va">+ // is a constant expression and thus an immediate invocation.</span></span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true" tabindex="-1"></a><span class="va">+ }</span></span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true" tabindex="-1"></a><span class="va">+</span></span>
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true" tabindex="-1"></a><span class="va">+ static_assert(overly_complicated() == 121);</span></span></code></pre></div>
</div>
<span> — <em>end example</em> ]</span>
</div>
Expand All @@ -844,8 +872,8 @@ <h2 data-number="2.3" id="feature-test-macro"><span class="header-section-number
<div class="std">
<blockquote>
<div>
<div class="sourceCode" id="cb6"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="st">- __cpp_­consteval <span class="diffdel">202211L</span></span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="va">+ __cpp_­consteval <span class="diffins">20XXXXL</span></span></span></code></pre></div>
<div class="sourceCode" id="cb7"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="st">- __cpp_­consteval <span class="diffdel">202211L</span></span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="va">+ __cpp_­consteval <span class="diffins">20XXXXL</span></span></span></code></pre></div>
</div>
</blockquote>
</div>
Expand Down

0 comments on commit a55dcaf

Please sign in to comment.