<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
   "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=US-ASCII">
<title>Issues with Constexpr</title>
</head>
<body>
<h1>Issues with Constexpr</h1>

<p>
ISO/IEC JTC1 SC22 WG21 N2826 = 09-0016 - 2009-02-05
</p>

<p>
Lawrence Crowl, crowl@google.com, Lawrence@Crowl.org
<br>
William M. Miller, Edison Design Group, wmm@edg.com
</p>


<h2>Problems</h2>

<p>
Two issues have been raised
with respect to the declaration, definition, and use
of <code>constexpr</code> functions.
This paper addresses those issues
based on concensus of the core working group in September 2008.
</p>


<h3>Core issue 695:
Compile-time calculation errors in constexpr functions
</h3>

<p>
<b>Section:</b> 5 [expr]
<b>Status:</b> drafting
<b>Submitter:</b> Mike Miller
<b>Date:</b> 9 June, 2008
</p>

<p>
Evaluating an expression like 1/0
is intended to produce undefined behavior during the execution of a program
but be ill-formed at compile time.
The wording for this is in 5 [expr] paragraph 4:
</p>

<blockquote>
<p>
If during the evaluation of an expression,
the result is not mathematically defined
or not in the range of representable values for its type,
the behavior is undefined,
unless such an expression appears
where an integral constant expression is required (5.19 [expr.const]),
in which case the program is ill-formed. 
</p>
</blockquote>

<p>
The formulation "appears where an integral constant expression is required"
is intended as an acceptable Standardese circumlocution for
"evaluated at compile time,"
a concept that is not directly defined by the Standard.
It is not clear that this formulation adequately covers constexpr functions.
</p>

<h4>Notes from the September, 2008 meeting:</h4>

<p>
The CWG felt that
the concept of "compile-time evaluation" needs to be defined
for use in discussing constexpr functions.
There is a tension between wanting to diagnose errors at compile time
versus not diagnosing errors that will not actually occur at runtime.
In this context, a constexpr function might never be invoked,
either in a constant expression context or at runtime,
although the requirement that the expression in a constexpr function
be a potential constant expression
could be interpreted as triggering the provisions of 5 [expr] paragraph 4.
</p>

<p>
There are also contexts in which it is not known in advance
whether an expression must be constant or not,
notably in the initializer of a const integer variable,
where the nature of the initializer
determines whether the variable can be used in constant expressions or not.
In such a case,
it is not clear whether an erroneous expression should be considered ill-formed
or simply non-constant
(and thus subject to runtime undefined behavior, if it is ever evaluated).
The consensus of the CWG was that an expression like 1/0
should simply be considered non-constant;
any diagnostic would result from the use of the expression
in a context requiring a constant expression.
</p>

<h3>Core issue 699:
Must constexpr member functions be defined in the class member-specification?
</h3>

<p>
<b>Section:</b> 7.1.5 [dcl.constexpr]
<b>Status:</b> drafting
<b>Submitter:</b> Mike Miller
<b>Date:</b> 26 June, 2008
</p>

<p>
According to 7.1.5 [dcl.constexpr] paragraph 1,
<p>

<blockquote>
<p>
The <code>constexpr</code> specifier
shall be applied only to the definition of
an object, function, or function template,
or to the declaration of a static data member
of a literal type (3.9 [basic.types]). 
</p>
</blockquote>

<p>
As a result,
a <code>constexpr</code> member function cannot be simply declared
in the class member-specification and defined later;
it must be defined in its initial declaration.
<p>

<p>
This restriction was not part of the initial proposal
but was added during the CWG review.
However, the original intent is still visible
in some of the wording in 7.1.5 [dcl.constexpr].
For example,
paragraph 2 refers to applying the <code>constexpr</code> specifier to
the "declaration" and not the "definition" of a function or constructor.
Although that is formally correct, as definitions are also declarations,
it could be confusing. Also, the example in paragraph 6 reads,
</p>

<blockquote><pre><code>
class debug_flag {
  public:
    explicit debug_flag(bool);
    constexpr bool is_on();    // error: debug_flag not literal type
    ...
</code></pre></blockquote>

<p>
when the proximate error is that
<code>is_on</code> is only declared, not defined.
There are also many occurrences of the <code>constexpr</code> specifier
in the library clauses where the member function is only declared, not defined.
</p>

<p>
It's not clear how much simplification is gained by this restriction.
There are reasons for defining ordinary inline functions
outside the class member-specification
(reducing the size and complexity of the class definition,
separating interface from implementation,
making the editing task easier
if program evolution results in an inline function being made non-inline, etc.)
that would presumably apply to constexpr member functions as well.
It seems feasible to allow
separate declaration and definition of a constexpr function;
it would simply not be permitted to use it in a constant expression
before the definition is seen
(although it could presumably still be used
in non-constant expressions in that region, like an ordinary inline function).
</p>

<p>
If the prohibition were relaxed
to allow separate declaration and definition of constexpr member functions,
some questions would need to be answered,
such as whether the constexpr specifier
must appear on both declaration and definition (the inline specifier need not).
If it can be omitted in one or the other,
there's a usability issue regarding the fact that constexpr implies const;
the const qualifier would need to be specified explicitly
in the declaration in which constexpr was omitted.
</p>

<p>
If the current restriction is kept,
the library clauses should state in an introduction
that a non-defining declaration of a constexpr member function
should be considered "for exposition only" and not literal code.
</p>

<h4>Notes from the September, 2008 meeting:</h4>

<p>
In addition to the original issues described above,
the question has arisen whether recursive constexpr functions
are or should be permitted.
Although they were originally desired by the proposers of the feature,
they were prohibited out of an abundance of caution.
However, the wording that specified the prohibition
was changed during the review process, inadvertently permitting them.
</p>

<p>
The CWG felt that there are sufficient use cases for recursion
that it should not be forbidden
(although a new minimum for recursion depth
should be added to Annex B [implimits]).
If mutual recursion is to be allowed,
forward declaration of constexpr functions must also be permitted
(answering the original question in this issue).
A call to an undefined constexpr function
in the body of a constexpr function
should be diagnosed when the outer constexpr function
is invoked in a context requiring a constant expression;
in all other contexts,
a call to an undefined constexpr function
should be treated as a normal runtime function call,
just as if it had been invoked with non-constant arguments.
</p>


<h3>Message c++std-core-13310:
Constexpr Recursion?
</h3>

<p>
<b>Submitter:</b> Lawrence Crowl
<b>Date:</b> 8 September, 2008
</p>

<p>
The working draft does not indicate whether or not
constexpr recursion is permitted.
Is it intended to be permitted?
My reading of the draft indicates that it is permitted,
but such a powerful implication probably needs a note.
</p>

<blockquote><pre><code>
constexpr unsigned int factorial( unsigned int n )
{ return n==0 ? 1 : n * factorial( n-1 ); }
</code></pre></blockquote>


<h2>Comments</h2>

<p>
The text to say "evaluated at translation time" does not seem necessary 
given the proposed resolution of making undefined results be
"not a constant expression".
</p>


<h2>Proposed Wording</h2>

<p>
We propose the following changes to the working draft.
</p>

<h3>5 Expressions [expr]</h3>

<p>
Edit paragraph 2 as follows.
</p>

<blockquote>

<p>
If during the evaluation of an expression,
the result is not mathematically defined
or not in the range of representable values for its type,
the behavior is undefined<del>,
unless such an expression appears
where an integral constant expression is required (5.19),
in which case the program is ill-formed</del>.
[<i>Note:</i>
most existing implementations of C++ ignore integer overflows.
Treatment of division by zero,
forming a remainder using a zero divisor,
and all floating point exceptions vary among machines,
and is usually adjustable by a library function.
&mdash;<i>end note</i>]
</p>


</blockquote>

<h3>5.19 Constant expressions [expr.const]</h3>

<p>
Edit paragraph 2 as follows.
</p>

<blockquote>

<p>
A <var>conditional-expression</var> is a constant expression
unless it involves one of the following
as a potentially evaluated subexpression (3.2),
but subexpressions of logical AND (5.14), logical OR (5.15),
and conditional (5.16) operations
that are not evaluated are not considered
[<i>Note:</i>
an overloaded operator invokes a function.
&mdash;<i>end note</i>]:
</p>

<ul>
<li>...</li>

<li>
an invocation of a function other than
a constexpr function
or a constexpr constructor
[<i>Note:</i>
overload resolution (13.3) is applied as usual
&mdash;<i>end note</i>]
</li>

<li>
<ins>a direct or indirect invocation of
an undefined constexpr function or a undefined constexpr constructor
outside the definition of
a constexpr function or a constexpr constructor</ins>
</li>

<li>
<ins>a result that is not mathematically defined
or not in the range of representable values for its type</ins>
</li>

<li>...</li>
</ul>

</blockquote>


<h3>7.1.5 The <code>constexpr</code> specifier [dcl.constexpr]</h3>

<p>
Edit paragraph 1 as follows.
</p>

<blockquote>
<p>
The <code>constexpr</code> specifier
shall be applied only to the definition of an object,
<ins>the declaration of a</ins>
<del>function,</del> <ins>function</ins> or function template,
or to the declaration of a static data member
of an effective literal type (3.9).
<ins>If any declaration of a function or function template
has the <code>constexpr</code> specifier,
then all its declarations
shall contain the <code>constexpr</code> specifier.
[<i>Note:</i>
An explicit specialization of a function template
is not a declaration of that template
and can thus differ from the template declaration
with respect to the <code>constexpr</code> specifier.
&mdash;<i>end note</i>]
</ins>
[<i>Note:</i>
function parameters cannot be declared constexpr.
&mdash;<i>end note</i>]
[<i>Example:</i>
</p>
<blockquote><pre><code>
<ins>constexpr int square(int x); // OK, declaration</ins>
<del>constexpr int square(int x) { // OK
  return x * x;
}</del>
constexpr int bufsz = 1024; // OK<ins>, definition</ins>
constexpr struct pixel { // error: pixel is a type
  int x;
  int y;
  <ins>constexpr pixel(int); // OK, declaration</ins>
};
<ins>constexpr pixel::pixel(int a)
  : x(square(a)), y(square(a)) { } // OK, definition</ins>
<ins>constexpr pixel small(2); // error: square not defined,
  // so small(2) not constant (5.19), so constexpr not satisfied</ins>
<ins>constexpr int square(int x) { // OK, definition
  return x * x;
}</ins>
<ins>constexpr pixel large(4); // OK, square defined</ins>
int next(constexpr int x) { // error<ins>: not for parameters</ins>
  return x + 1;
}
extern constexpr int memsz; // error: not a definition
</code></pre></blockquote>
<p>
&mdash;<i>end example</i>]
</p>
</blockquote>


<h3>17.6.5.5++ <code>constexpr</code> function declarations [constexpr.dcl]</h3>

<p>
After section 17.6.5.5 Member functions [member.functions],
add the following section.
</p>

<blockquote>
<p>
Implementations shall provide definitions
for any non-defining declarations
of <code>constexpr</code> functions and constructors
within the associated header files.
</p>
</blockquote>


<h3>Annex B (informative) Implementation quantities [implimits]</h3>


<p>
Edit paragraph 2 as follows.
</p>

<blockquote>
<ul>
<li>...</li>
<li>Nested external specifications [1 024].</li>
<li><ins>Recursive constexpr function invocations [512].</ins></li>
<li>Template arguments in a template declaration [1 024].</li>
<li>Recursively nested template instantiations [17].</li>
<li>Recursively nested implicit concept map definitions [1 024].</li>
<li>...</li>
</ul>
</blockquote>

</body>
</html>
