<html><head><meta http-equiv="Content-Type" content="text/html; charset=windows-1252"></head>

<style type="text/css">
  blockquote.stdins { color: #000000; background-color: #A0FFA0; }
  ins { text-decoration:none; background-color:#A0FFA0 }
  del { text-decoration:line-through; background-color:#FFA0A0 }
  tab { padding-left: 4em }
</style>
<body>
<p align=right><b>P1073R3, 2018-11-06</b>
<br/>CWG
</p>

<p align=right>
<br/>Richard Smith (richard@metafoo.co.uk)  
<br/>Andrew Sutton (andrew.n.sutton@gmail.com)  
<br/>Daveed Vandevoorde (daveed@edg.com)
</p>

<h1 align="center">Immediate functions</h1>

<h4>Revisions</h4>
<p>
Revision 0: Original proposal with wording.
</p>
<p>
Revision 1: Introduce <tt>constexpr!</tt> token and allow it in lambda
            expressions.
</p>
<p>
Revision 2: Replace <tt>constexpr!</tt> by <tt>consteval</tt>.
</p>
<p>
Revision 3: Address CWG review notes.
</p>

<h3>Introduction and motivation</h3>

<p>
The <tt>constexpr</tt> specifier applied to a function or member function
indicates that a call to that function might be valid in a context requiring
a constant-expression.  It does not <i>require</i> that every such
call be a constant-expression.  Sometimes, however, we want to express
that a function should <i>always</i> produce a constant when called (directly
or indirectly), and a non-constant result should produce an error.  Such a
function is called an <i>immediate</i> function.  We propose the <i>decl-specifier</i>
<tt>consteval</tt> for that purpose:

<pre><code class="language-c++">consteval int sqr(int n) {
  return n*n;
}
constexpr int r = sqr(100);  // Okay.
int x = 100;
int r2 = sqr(x);  // Error: Call does not produce a constant.
</code></pre>
</p>
<p>
There is one exception to the rule that a call to a <tt>consteval</tt>
function must be a constant-expression: If the call appears directly in another
<tt>consteval</tt> function, it need not be a constant-expression at that point
(since a call to the enclosing function would ultimately have to produce a core
constant expression, we do not have to worry about ever having to evaluate that
nested call at run time).  This permits composition of <tt>consteval</tt>
functions:

<pre><code class="language-c++">consteval int sqrsqr(int n) {
  return sqr(sqr(n)); // Not a constant-expression at this  point,
}                     // but that's okay.

constexpr int dblsqr(int n) {
  return 2*sqr(n); // Error: Enclosing function is not
}                  // consteval.
</code></pre>
</p>
<p>
Finally, as is the case with a bound member function (e.g., "<tt>x.f</tt>"),
a <tt>consteval</tt> function can only be called; no pointer or reference
to it can be formed:

<pre><code class="language-c++">using Int2Int = int(int);
Int2Int *pf = sqr;  // Error.
</code></pre>
</p>
<p>
One consequence of this specification is that an immediate function never needs
to be seen by a back end.  That means that immediate functions are an alternative
to many function-style macros.  It also means that, unlike plain <tt>constexpr</tt>
functions, <tt>consteval</tt> functions are unlikely to show up in symbolic
debuggers.  That runs into the broader issue that programmers currently have few
tools to debug compile-time evaluation: This proposal does not aim at solving
that problem in any way.
</p>


<h4>Variables</h4>
<p>
Given that <tt>consteval</tt> functions are a useful alternative to function-style
macros, it is natural to wonder whether we could make <tt>consteval</tt>
<i>variables</i> a useful alternative to non-function-style macros.  We'd call such
variables &mdash; which would never be seen by a back end &mdash; <i>immediate</i> variables:
<pre><code class="language-c++">consteval int RN = 42;
int LN = 42;

int f(int const&);

int r1 = f(LN);  // Direct reference binding.
int r2 = f(RN);  // Not a direct binding (temporary created).
</code></pre>
</p>
<p>
Unfortunately, the exact specification of such a facility raises some difficult
questions, some of which relate to the topic of enabling class types for nontype
template parameters as proposed in <a href="https://wg21.link/p0732r1">P0732R1</a>.
This paper therefore does not pursue that extension at this time.
</p>

<h4>Notes</h4>

<p>
The desire for functionality like this comes up regularly.  Sometimes, the motivation
is to eliminate macros, and sometimes it just falls naturally out of the development
process (e.g., helper functions meant to create nontype template argument values).
</p>
<p>
The impetus for the present paper, however, is the work being done by SG7 in the
realm of compile-time reflection.  There is now general agreement that future language
support for reflection should use constexpr functions, but since "reflection functions"
typically <i>have</i> to be evaluated at compile time, they will in fact likely be
<i>immediate</i> functions.
</p>
<p>
The general principles of this facility were first discussed in Kona (2017) as part
of the discussion of P0595r0.  At the time, the following poll was recorded:
<blockquote>
	Provide a way to write a function that is guaranteed to be produce a constant
	expression, violations diagnosed at call site? (Direction poll for [immediate
	functions], ignoring syntax):<br/>
	SF: 8 | F: 13 | N: 2 | A: 0 | SA: 0
</blockquote>
(See <a href="http://wiki.edg.com/bin/view/Wg21kona2017/P0595R0">http://wiki.edg.com/bin/view/Wg21kona2017/P0595R0</a>.
The syntax under consideration at that time was <tt>do constexpr</tt> instead of <tt>consteval</tt>.)
</p>
<p>
At the Rapperswil meeting in 2018, essentially this proposal
<a href="http://wiki.edg.com/bin/view/Wg21rapperswil2018/P1073R0-Rap18">was
accepted</a> by EWG except the specifier <tt>constexpr!</tt> was used instead
of <tt>consteval</tt>. There was some discussion of syntax at the time, but the
proposed spelling had reasonably strong support:
<blockquote>
	Proposal as presented for C++20<br/>
	SF: 19 | F: 22 | N: 1 | A: 2 | SA: 0<br/>
	<br/>
	Use "true constexpr" instead of "constexpr!"<br/?
	SF: 5 | F: 8 | N: 14 | A: 8 | SA: 10<br/>
</blockquote>
However, reflector discussions later indicated an alternative would be
preferred.  This paper presents one such an alternative.  Another that
is also liked is <tt>constfold</tt> (if that happens to be preferred,
a simple search-and-replace in the proposed wording below is all that
is needed).
Both <tt>consteval</tt> and <tt>constfold</tt> were searched for in Google's extensive codebase
(which includes many open-source projects in addition to Google's own
code) and no conflicts were found.
</p>


<h4>Acknowledgments</h4>

Thanks to Vitorrio Romeo for catching a missing wording change.


<h2>Wording changes</h2>

<p>Add the keyword <tt>consteval</tt> to Table 5 ("Keywords")
   in [lex.key].</p>

<p>Add to the grammar of [dcl.spec] paragraph 1:</p>  
<blockquote style="padding-left: 30px;">
	<i>decl-specifier</i>:<br/>
	<tab><i>storage-class-specifier</i><br/>
	<tab><i>defining-type-specifier</i><br/>
	<tab><i>function-specifier</i><br/>
	<tab><tt>friend</tt><br/>
	<tab><tt>typedef</tt><br/>
	<tab><tt>constexpr</tt><br/>
	<tab><ins><tt>consteval</tt></ins><br/>
	<tab><tt>inline</tt>
</blockquote>

<p>Update [expr.prim.lambda] paragraph 3 as follows:</p>
<blockquote style="padding-left: 30px;">
	In the <i>decl-specifier-seq</i> of the <i>lambda-declarator</i>,
	each <i>decl-specifier</i> shall <del>either</del> be
	<ins>one of</ins> <tt>mutable</tt><ins>, </ins><del> or</del>
	<tt>constexpr</tt><ins>, or <tt>consteval</tt></ins>.
	[ <i>Note:</i> The trailing <i>requires-clause</i> is described
	  in Clause 11. <i>&mdash; end note</i> ]
</blockquote>


<p>Update [expr.prim.lambda.closure] paragraph 4 as follows:</p>
<blockquote style="padding-left: 30px;">
... The function call operator or any given operator template
specialization is a constexpr function if either the corresponding 
<i>lambda-expression</i>’s <i>parameter-declaration-clause</i>
is followed by <tt>constexpr</tt><ins> or <tt>consteval</tt></ins>,
or it satisfies the requirements for a constexpr function (9.1.5).
<ins>It is an immediate function (_dcl.constexpr_) if the corresponding 
<i>lambda-expression</i>’s <i>parameter-declaration-clause</i>
is followed by <tt>consteval</tt>.</ins> ...
</blockquote>

<p>Update [expr.prim.lambda.closure] paragraph 7 as follows:</p>
<blockquote style="padding-left: 30px;">
... F is a constexpr function if the function call operator is a constexpr
function
<ins>and is an immediate function if the function call operator is an
immediate function</ins>.
</blockquote>


<p>Update [dcl.constexpr] paragraph 8 as follows:</p>
<blockquote style="padding-left: 30px;">
	The <tt>constexpr</tt> <ins>and <tt>consteval</tt> </ins>specifier<ins>s have</ins><del> has</del>
	no effect on the type of a constexpr function or a constexpr constructor.
</blockquote>

<p>Add a paragraph after paragraph 2 of [expr.prim.id]:</p>
<blockquote style="padding-left: 30px;" class="stdins">
An <i>id-expression</i> that denotes an immediate function
(_dcl.constexpr_) shall appear as a subexpression of an immediate
invocation or in an immediate function context (_expr.const_).
</blockquote>


<p>Change in [expr.const] paragraph 6:</p>
<blockquote style="padding-left: 30px;">
...
<ul>
<li>...</li>
<li>if the value is of pointer type, it contains the address of an object
    with static storage duration, the address past the end of such an object
    (7.6.6), the address of a <ins>non-immediate</ins> function, or a null pointer
    value, and
</li>
<li><ins>if the value is of pointer-to-member-function type, it does not designate
     an immediate function, and</ins></li>
<li>...</li>
</ul>
...
<br>
An entity is a permitted result of a constant expression if it is an object
with static storage duration that is either not a temporary object or is a
temporary object whose value satisfies the above constraints, or it is a
<ins>non-immediate</ins> function.
<ins>[<i>Example:</i>
	<pre><ins><tt>
  consteval int f() { return 42; }
  consteval auto g() { return f; }
  consteval int h(int (*p)() = g()) { return p(); }
  constexpr int r = h();   // OK
  constexpr auto e = g();  // ill-formed: a pointer to an immediate function is
                           // not a permitted result of a constant expression
	</tt></ins></pre>
<i>--end example</i>]</ins>
</blockquote>



<p>In [expr.const] insert a new paragraph immediately preceding paragraph 8 (the paragraph that
defines <i>potentially constant evaluated</i>) with the following context:</p>
<blockquote style="padding-left: 30px;">
  <ins>An expression or conversion is <i>in an immediate function context</i>
       if it is potentially evaluated and its innermost non-block
       scope is a function parameter scope of an immediate function.
       An expression or conversion is an <i>immediate invocation</i> if it is
       an explicit or implicit invocation of an immediate function and is not
       in an immediate function context.
    An immediate invocation shall be a constant expression.
    [<i>Note:</i> An immediate invocation is evaluated even in an unevaluated
     operand.  <i>--end note</i>] </ins>
</blockquote>		

<p>In [intro.execution] paragraph 5 add a bullet:</p>
<blockquote style="padding-left: 30px;">
<ul>
A <i>full-expression</i> is
  <li>...</li>
  <li>a <i>constant-expression</i> (7.7),</li>
  <li><ins>an immediate invocation (_expr.const_)</ins></li>
  <li>...</li>
</ul>
</blockquote>

<p>In [decl.type.simple] paragraph 5 make the following change in the first
sentence:</p>
<blockquote style="padding-left: 30px;">
If the operand of a decltype-specifier is a prvalue <ins>and is not a
(possibly parenthesized) immediate invocation (_expr.const_)</ins>,
the temporary...
</blockquote>

<p>Insert a bullet after the first bullet (8.1) of the definition of
<i>potentially constant evaluated</i> in [expr.const] paragraph 8:</p>
<blockquote style="padding-left: 30px;">
An expression <ins>or conversion</ins> is <i>potentially constant evaluated</i>
if it is:
<ul>
	<li> ...</li>
	<li><ins>an immediate invocation,</ins></li>
	<li> ...</li>
</ul>
...
</blockquote>
and add an example at the end of the paragraph:
<blockquote style="padding-left: 30px;">
	<ins>[ <i>Example:</i>
	<pre><ins><tt>
  struct N {
    constexpr N() {}
    N(N const&) = delete;
  };
  template&lt;typename T&gt; constexpr void bad_assert_copyable() { T t; T t2 = t; }
  using ineffective = decltype(bad_assert_copyable&lt;N&gt;());
    // bad_assert_copyable&lt;N&gt; is not needed for constant evaluation
    // (and thus not instantiated)
  template&lt;typename T&gt; consteval void assert_copyable() { T t; T t2 = t; }
  using check = decltype(assert_copyable&lt;N&gt;());
    // error: assert_copyable&lt;N&gt; is instantiated (because it is needed for constant
    // evaluation), but the attempt to copy t is ill-formed
	</tt></ins></pre>
	<i>&mdash; end example</i> ]</ins>
</blockquote>

<p>Append to [dcl.spec] paragraph 2:</p>  
<blockquote style="padding-left: 30px;">
	<ins>The <tt>constexpr</tt> and <tt>consteval</tt> <i>decl-specifiers</i> shall not both appear in a
	<i>decl-specifier-seq</i>.</ins>
</blockquote>

<p>Update [dcl.constexpr] paragraph 1 as follows:</p>
<blockquote style="padding-left: 30px;">
	The <tt>constexpr</tt> specifier shall be applied only to the definition of a variable or
	variable template or the declaration of a function or function template.
	<ins>The <tt>consteval</tt> specifier shall be applied only to the declaration of a
	function or function template.</ins>	A function or static data member declared with the <tt>constexpr</tt>
	<ins>or	<tt>consteval</tt> </ins>specifier is implicitly an inline function or variable (10.1.6). If any
	declaration of a function or function template has a <tt>constexpr</tt> <ins> or
	<tt>consteval</tt> </ins>specifier, then all its declarations shall contain
	<del>the constexpr</del><ins>that same</ins> specifier. [ <i>Note:</i> An explicit specialization can differ
	from the template declaration with respect to the <tt>constexpr</tt>
	<ins>or <tt>consteval</tt> </ins>specifier. <i>&mdash; end note</i> ]
	[<i>Note:</i> Function parameters cannot be declared <tt>constexpr</tt>. <i>&mdash; end note</i> ]
</blockquote>

<p>Update [dcl.constexpr] paragraph 2 as follows:</p>
<blockquote style="padding-left: 30px;">
	A <tt>constexpr</tt> <ins>or <tt>consteval</tt> </ins>specifier used in the declaration of a function
	that is not a constructor declares that function to be a <i>constexpr function</i>. Similarly, a
	<tt>constexpr</tt> <ins>or <tt>consteval</tt> </ins>specifier used in a constructor declaration
	declares that constructor to be a <i>constexpr constructor</i>.<ins>  A function or constructor declared
	with the <tt>consteval</tt> specifier is called an <i>immediate function</i>. A destructor, an
	allocation function, or a deallocation function shall not be declared with the <tt>consteval</tt>
	specifier.</ins>
</blockquote>
<p>Update [dcl.fct.def.default] paragraph 3 as follows:</p>
<blockquote style="padding-left: 30px;">
An explicitly-defaulted function that is not defined as deleted may be declared
<tt>constexpr</tt> <ins>or <tt>consteval</tt> </ins>only if it would have been implicitly
declared as <tt>constexpr</tt>. [...]
</blockquote>

<p>Add a footnote to [class.virtual] paragraph 1:</p>
<blockquote style="padding-left: 30px;">
... A class that declares or inherits a virtual function is called a
polymorphic class.<ins>[Footnote: If all virtual functions are immediate
functions, the class is still polymorphic even though its internal
representation might not otherwise require any additions for that polymorphic
behavior.]</ins>
</blockquote>

<p>Add the following paragraph following [class.virtual] paragraph 17:</p>
<blockquote style="padding-left: 30px;" class="stdins">
	A <tt>consteval</tt> virtual function shall not override a virtual
	function that is not <tt>consteval</tt>. A <tt>consteval</tt> virtual
	function shall not be overridden by a virtual function that is not
	<tt>consteval</tt>.
</blockquote>

<p>Update [temp.explicit] paragraph 1 as follows:</p>
<blockquote style="padding-left: 30px;">
	[...]An explicit instantiation of a function template, member function of a class template,
	or variable template shall not use the <tt>inline</tt><del> or</del><ins>,</ins>
	<tt>constexpr</tt><ins>, or <tt>consteval</tt></ins> specifiers.
</blockquote>


<p>Change [diff.cpp17.lex] paragraph 1 as follows:</p>
<blockquote style="padding-left: 30px;">
	<p>...<br/>
	<b>Rationale:</b> ... <ins>The <tt>consteval</tt> keyword is added to declare
		immediate functions (_dcl.constexpr_).</ins><br/>
	<b>Effect on original feature:</b> Valid ISO C++ 2017 code using
	<tt>concept</tt><ins>, <tt>consteval</tt>,</ins> or <tt>requires</tt>
	as an identifier is not valid in this International Standard.</p>
</blockquote>

</body></html>

