<!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>Fixing inconsistencies between `constexpr` and `consteval` functions</title>
        
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Microsoft/vscode/extensions/markdown-language-features/media/markdown.css">
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/Microsoft/vscode/extensions/markdown-language-features/media/highlight.css">
        
        <style>
.task-list-item { list-style-type: none; } .task-list-item-checkbox { margin-left: -20px; vertical-align: middle; }
</style>
        <style>
            body {
                font-family: -apple-system, BlinkMacSystemFont, 'Segoe WPC', 'Segoe UI', 'Ubuntu', 'Droid Sans', sans-serif;
                font-size: 14px;
                line-height: 1.6;
            }
        </style>
        
        
    </head>
    <body class="vscode-light">
        <h1 id="fixing-inconsistencies-between-constexpr-and-consteval-functions">Fixing inconsistencies between <code>constexpr</code> and <code>consteval</code> functions</h1>
<pre>Document Number: P1937R1
Date: 2020-01-12
Author: David Stone (david.stone@uber.com, david@doublewise.net)
Audience: Core Working Group (CWG)</pre>
<h2 id="summary">Summary</h2>
<p>A <code>consteval</code> function is the same as a <code>constexpr</code> function except that:</p>
<ol>
<li>A <code>consteval</code> function is guaranteed to be evaluated at compile time.</li>
<li>You cannot have a pointer to a <code>consteval</code> function except in the body of another <code>consteval</code> function.</li>
<li>All overrides of a virtual function must be <code>consteval</code> if the base function is <code>consteval</code>, otherwise they must not be <code>consteval</code>.</li>
<li>A <code>consteval</code> function is evaluated even in contexts that would otherwise be unevaluated.</li>
</ol>
<p>The first point is the intended difference between the two functions. The second point is a consequence of the first. The third point (<code>virtual</code> functions) ends up making sense as a difference between them because of what is fundamentally possible. The final point seems like an unfortunate inconsistency in the language. This paper proposes changing the rules surrounding bullet 4 to unify the behavior of <code>consteval</code> and <code>constexpr</code> functions for C++20.</p>
<h2 id="revision-history">Revision history</h2>
<h3 id="since-r0">Since R0</h3>
<ul>
<li>Removed section on virtual functions: it will be its own paper in the future, targeted at C++23.</li>
<li>Added a small piece of wording</li>
</ul>
<h2 id="unevaluated-contexts">Unevaluated contexts</h2>
<p>Requiring evaluation of <code>consteval</code> functions in unevaluated contexts does not seem necessary. When I <a href="https://lists.isocpp.org/core/2019/09/7249.php">asked about this discrepancy on the core reflector</a>, the answer that I got was essentially that evaluation of a <code>consteval</code> function may have side-effects on the abstract machine, and we would like to preserve these side-effects. However, <code>consteval</code> functions are not special in this ability, so it seems strange to have a rule that makes them special. It seems to me that we should either</p>
<ol>
<li>not have a special case for <code>consteval</code>, which would mean that it is not evaluated in an unevaluated operand, or</li>
<li>Rethink the concept of &quot;unevaluated operands&quot;.</li>
</ol>
<p>This paper argues in favor of option 1, as option 2 is a breaking change that doesn't seem to bring much benefit.</p>
<p>My understanding is that the status quo means the following is valid:</p>
<pre><code><code><div>constexpr auto add1(auto lhs, auto rhs) {
    return lhs + rhs;
}
using T = decltype(add1(std::declval&lt;int&gt;(), std::declval&lt;int&gt;()));
</div></code></code></pre>
<p>but this very similar code is ill-formed</p>
<pre><code><code><div>consteval auto add2(auto lhs, auto rhs) {
    return lhs + rhs;
}
using T = decltype(add2(std::declval&lt;int&gt;(), std::declval&lt;int&gt;()));
</div></code></code></pre>
<h2 id="wording">Wording</h2>
<p>Note: this wording is presumed incomplete. There is a note stating that <code>consteval</code> functions are always evaluated, but I cannot find where the normative wording actually states this.</p>
<p>Modify [expr.const], paragraph 13, as follows:</p>
<blockquote>
<p><s>[ Note: A manifestly constant-evaluated expression is evaluated even in an unevaluated operand. — end note ]</s></p>
</blockquote>

    </body>
    </html>