<html>
<style>
ins {background-color:#A0FFA0}
del {background-color:#FFA0A0}
</style>
<title>Allowing constexpr for reference parameters</title>
<body>
Jason Merrill
<br>2010-03-12
<br>N3078=10-0068

<h2>Constexpr functions with reference parameters</h2>

This wording is revised from the wording in
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3039.pdf">N3039</a>
by Bjarne Stroustrup, Alisdair Meredith and Gabriel Dos Reis; please see that paper for rationale.

<p>The changes in this document are primarily to
broaden the allowance to non-const references.  Any problematic operation
on a non-const reference is still prohibited because it would prevent the
function body from being a potential constant expression.

<h4>Proposed wording</h4>

7.1.5/3, second and third bullets:

<blockquote>
<ul>
  <li>its return type shall be a literal type <ins>or a reference to literal type</ins></li>
  <li>each of its parameter types shall be a literal type <ins>or a
      reference to literal type</ins></li>
</ul>
</blockquote>

7.1.5/4, first bullet:

<blockquote>
<ul>
  <li>each of its parameter types shall be a literal type <ins>or a
      reference to literal type</ins></li>
</ul>
</blockquote>

5.19/2, third bullet:

<blockquote>
<ul>
<li>a<ins>n</ins> <del>direct or indirect</del> invocation of an undefined
  constexpr function or an undefined constexpr constructor outside the
  definition of a constexpr function or a constexpr constructor;</li>
<li><ins>an invocation of a constexpr function with arguments that, when
implicitly converted to the corresponding parameter types and substituted
for the corresponding parameters in the potential constant expression of
the constexpr function, and the resulting expression implicitly converted
to the return type, do not produce a constant expression;<br>
[ Example:</ins>
<pre>
  <ins>constexpr const int *addr (const int &amp;ir) { return &amp;ir; } // OK</ins>
  <ins>static const int x = 5;</ins>
  <ins>constexpr const int *xp = addr(x); // OK, (const int *)&amp;(const int &amp;)x is an address constant expression</ins>
  <ins>constexpr const int *tp = addr(5); // error, initializer for constexpr variable not a constant expression</ins>
  <ins>                                   // (const int *)&amp;(const int &amp;)5 is not a constant expression because it takes the address of a temporary</ins>
</pre>
<ins>--end example ]</ins></li>
</ul>
</blockquote>

5.19/2, bullets 6-9:

<blockquote>
<ul><li>an lvalue-to-rvalue conversion (4.1) unless it is applied to
<ul>
 <li>a glvalue of integral or enumeration type that refers to a non-volatile const variable with a
   preceding initialization, initialized with a constant expression, or</li>
 <li>a glvalue of literal type that refers to a non-volatile object defined
   with constexpr, or that refers to a sub-object of such an
   object<del>;</del><ins>, or</ins></li>
 <li><ins>a glvalue of literal type that refers to a non-volatile temporary
   object initialized with a constant expression;<br> [ Footnote: The
   temporary must be part of the constant expression, as any longer-lived
   temporary would have to be bound to a reference, and reference variables
   cannot appear in a constant expression --end footnote]</ins></li>
</ul>
</li>
  <li>an array-to-pointer conversion (4.2) that is applied to a glvalue that <ins>does not</ins> designate<del>s</del> an object with <ins>static</ins><del>thread or automatic</del> storage duration;</li>
  <li>a unary operator &amp; (5.3.1) that is applied to an lvalue that <ins>does not</ins> designate<del>s</del> an object with <ins>static</ins><del>thread or automatic</del>
    storage duration;</li>

  <li>an id-expression that refers to a variable or data member of
  reference type <ins>[ Footnote: use of a reference parameter of a
  constexpr function does not prevent the body from being a potential
  constant expression because the parameters are replaced by constant
  expressions during that determination, and later by arguments to a
  call. --end footnote ]</ins>;</li>
</ul>
</blockquote>

5.19/6:
<blockquote>
  An expression is a potential constant expression if it is a constant
  expression when all occurrences of function parameters are replaced <ins>as follows:</ins>
<ul>
  <li><ins>for non-reference parameters,</ins> by arbitrary <ins>prvalue</ins> constant
 expressions of the appropriate type<ins>s;</ins></li>
  <li><ins>for lvalue reference parameters, by arbitrary variables of the
  referred-to types with static storage duration initialized with constant
  expressions; or</ins></li>
  <li><ins>for rvalue reference parameters, by arbitrary prvalue constant
  expressions of the referred-to types implicitly converted to the types of
  the parameters.</ins></li>
</blockquote>

7.1.5:
<blockquote>
  If the instantiated template specialization of a constexpr function
  template would fail to satisfy the requirements for a constexpr function
  or constexpr constructor, the constexpr specifier is ignored.
<p><ins>A call to a constexpr function produces the same result as a call
to an equivalent non-constexpr function in all respects except that a call to a
constexpr function can appear in a constant expression.</ins></p>
</blockquote>
</body>
</html>
