<HTML>
<HEAD>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<TITLE>
    CWG Issue 1454</TITLE>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<STYLE TYPE="text/css">
  INS { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  .INS { text-decoration:none; background-color:#D0FFD0 }
  DEL { text-decoration:line-through; background-color:#FFA0A0 }
  .DEL { text-decoration:line-through; background-color: #FFD0D0 }
  @media (prefers-color-scheme: dark) {
    HTML { background-color:#202020; color:#f0f0f0; }
    A { color:#5bc0ff; }
    A:visited { color:#c6a8ff; }
    A:hover, a:focus { color:#afd7ff; }
    INS { background-color:#033a16; color:#aff5b4; }
    .INS { background-color: #033a16; }
    DEL { background-color:#67060c; color:#ffdcd7; }
    .DEL { background-color:#67060c; }
  }
  SPAN.cmnt { font-family:Times; font-style:italic }
</STYLE>
</HEAD>
<BODY>
<P><EM>This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21
  Core Issues List revision 118b.
  See http://www.open-std.org/jtc1/sc22/wg21/ for the official
  list.</EM></P>
<P>2025-09-28</P>
<HR>
<A NAME="1454"></A><H4>1454.
  
Passing constants through <TT>constexpr</TT> functions via references
</H4>
<B>Section: </B>7.7&#160; [<A href="https://wg21.link/expr.const">expr.const</A>]
 &#160;&#160;&#160;

 <B>Status: </B>CD3
 &#160;&#160;&#160;

 <B>Submitter: </B>Richard Smith
 &#160;&#160;&#160;

 <B>Date: </B>2011-12-27<BR>


<P>[Moved to DR at the October, 2012 meeting.]</P>



<P>The current wording incorrectly appears to make the following
example ill-formed:</P>

<PRE>
   constexpr const int &amp;f(const int &amp;n) { return n; }
   constexpr int k = f(0);   // ill-formed
</PRE>

<P><B>Proposed resolution (February, 2012):</B></P>

<OL>
<LI><P>Change 7.7 [<A href="https://wg21.link/expr.const#2">expr.const</A>] paragraph 2 as follows:</P></LI>

<BLOCKQUOTE>

<P>A <I>conditional-expression</I> is a <I>core constant
expression</I> unless it involves one of the following...</P>

<UL>
<LI><P>...</P></LI>

<LI><P>an invocation of a <TT>constexpr</TT> function with arguments
that, when substituted by function invocation substitution
(9.2.6 [<A href="https://wg21.link/dcl.constexpr">dcl.constexpr</A>]), do not produce a <INS>core</INS>
constant expression; [<I>Example:</I>...</P></LI>

<LI><P>an invocation of a <TT>constexpr</TT> constructor with
arguments that, when substituted by function invocation substitution
(9.2.6 [<A href="https://wg21.link/dcl.constexpr">dcl.constexpr</A>]), do not produce all <INS>core</INS>
constant expressions for the constructor calls and full-expressions in
the <I>mem-initializer</I>s; [<I>Example:</I>...</P></LI>

<LI><P>...</P></LI>

<LI><P>an lvalue-to-rvalue conversion (7.3.2 [<A href="https://wg21.link/conv.lval">conv.lval</A>])
unless it is applied to</P></LI>

<UL>
<LI><P>...</P></LI>

<LI><P>a glvalue of literal type that refers to a non-volatile
temporary object whose lifetime has not ended, initialized with a
<INS>core</INS> constant expression;</P></LI>

</UL>

<LI><P>...</P></LI>

<LI><P>an <I>id-expression</I> that refers to a variable or data
member of reference type unless the reference has a preceding
initialization<DEL>, initialized with a constant expression;</DEL>
<INS>and either</INS>
</P></LI>

<UL>
<LI><P><INS>it is initialized with a constant expression or</INS></P></LI>

<LI><P><INS>it is a non-static data member of a temporary object whose
lifetime has not ended and is initialized with a core constant
expression;</INS></P></LI>

</UL>

<LI><P>...</P></LI>

</UL>

</BLOCKQUOTE>

<LI><P>Change 7.7 [<A href="https://wg21.link/expr.const#3">expr.const</A>] paragraph 3 as follows,
dividing it into two paragraphs:</P></LI>

<BLOCKQUOTE>

<P>
<DEL>A <I>literal constant expression</I> is a prvalue core
constant expression of literal type, but not pointer type.</DEL> An
<I>integral constant expression</I> is <DEL>a literal constant</DEL>
<INS>an</INS> expression of integral or unscoped enumeration
type<INS>, implicitly converted to a prvalue, where the converted
expression is a core constant expression</INS>. [<I>Note:</I> Such
expressions may be used as array bounds (9.3.4.5 [<A href="https://wg21.link/dcl.array">dcl.array</A>],
7.6.2.8 [<A href="https://wg21.link/expr.new">expr.new</A>]), as bit-field lengths (11.4.10 [<A href="https://wg21.link/class.bit">class.bit</A>]), as enumerator initializers if the underlying type is not
fixed (9.8.1 [<A href="https://wg21.link/dcl.enum">dcl.enum</A>]), as null pointer constants
(7.3.12 [<A href="https://wg21.link/conv.ptr">conv.ptr</A>]), and as alignments (9.13.2 [<A href="https://wg21.link/dcl.align">dcl.align</A>]).  &#8212;<I>end note</I>] A <I>converted constant
expression</I> of type <TT>T</TT> is <DEL>a literal constant</DEL>
<INS>an</INS> expression, implicitly converted to <INS>a prvalue
of</INS> type <TT>T</TT>, where the <DEL>implicit conversion (if any)
is permitted in a literal</DEL> <INS>converted expression is a
core</INS> constant expression and the implicit conversion sequence
contains only user-defined conversions, lvalue-to-rvalue conversions
(7.3.2 [<A href="https://wg21.link/conv.lval">conv.lval</A>]), integral promotions (7.3.7 [<A href="https://wg21.link/conv.prom">conv.prom</A>]), and integral conversions (7.3.9 [<A href="https://wg21.link/conv.integral">conv.integral</A>])
other than narrowing conversions (9.5.5 [<A href="https://wg21.link/dcl.init.list">dcl.init.list</A>]). [<I>Note:</I> such expressions may be used as case
expressions (8.5.3 [<A href="https://wg21.link/stmt.switch">stmt.switch</A>]), as enumerator initializers
if the underlying type is fixed (9.8.1 [<A href="https://wg21.link/dcl.enum">dcl.enum</A>]), and as
integral or enumeration non-type template arguments (13.4 [<A href="https://wg21.link/temp.arg">temp.arg</A>]). &#8212;<I>end note</I>]</P>

<P>
<INS>A <I>literal constant expression</I> is a prvalue core
constant expression of literal type, but not pointer type (after
conversions as required by the context).  For a literal constant
expression of array or class type, each subobject of its value shall
have been initialized by a constant expression.</INS> A <I>reference
constant expression</I> is an lvalue core constant expression that
designates an object with static storage duration or a function.  An
<I>address constant expression</I> is a prvalue core constant
expression <INS>(after conversions as required by the context) of type
<TT>std::nullptr_t</TT> or</INS> of pointer type that evaluates to the
address of an object with static storage duration, to the address of a
function, or to a null pointer value<DEL>, or a prvalue core constant
expression of type <TT>std::nullptr_t</TT></DEL>.  Collectively,
literal constant expressions, reference constant expressions, and
address constant expressions are called
<I>constant expressions</I>.</P>

</BLOCKQUOTE>

<LI><P>Change the second example 9.2.6 [<A href="https://wg21.link/dcl.constexpr">dcl.constexpr</A>] paragraph
5 as follows:</P></LI>

<PRE>
  constexpr int f(bool b)
    { return b ? throw 0 : 0; }                  //<SPAN CLASS="cmnt"> OK</SPAN>
  constexpr int f() { <DEL>throw 0</DEL> <INS>return f(true)</INS>; }  //<SPAN CLASS="cmnt"> ill-formed, no diagnostic required</SPAN>
  ...
</PRE>

</OL>

<P>This resolution also resolves <A HREF="1455.html">issue 1455</A>.</P>

<BR><BR>
</BODY>
</HTML>
