This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 119a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2025-12-20
[Voted into WP at October, 2009 meeting.]
According to 9.2.6 [dcl.constexpr] paragraph 1,
Theconstexpr specifier shall be applied only to thedefinition of an object, function, or function template, or to thedeclaration of a static data member of a literal type (6.9 [basic.types]).
As a result, a constexpr member function cannot be simply declaredin the classmember-specification and defined later; it mustbe defined in its initial declaration.
This restriction was not part of the initial proposal but was addedduring the CWG review. However, the original intent is still visiblein some of the wording in 9.2.6 [dcl.constexpr]. For example,paragraph 2 refers to applying theconstexpr specifier to the“declaration” and not the “definition” of afunction or constructor. Although that is formally correct, asdefinitions are also declarations, it could be confusing. Also, theexample in paragraph 6 reads,
class debug_flag { public: explicit debug_flag(bool); constexpr bool is_on(); // error:debug_flag not literal type ...when the proximate error is thatis_on is only declared,not defined. There are also many occurrences of theconstexprspecifier in the library clauses where the member function is onlydeclared, not defined.
It's not clear how much simplification is gained by this restriction.There are reasons for defining ordinary inline functions outside theclassmember-specification (reducing the size and complexity ofthe class definition, separating interface from implementation, makingthe editing task easier if program evolution results in an inlinefunction being made non-inline, etc.) that would presumably apply toconstexpr member functions as well. It seems feasible to allowseparate declaration and definition of a constexpr function; it wouldsimply not be permitted to use it in a constant expression before thedefinition is seen (although it could presumably still be used innon-constant expressions in that region, like an ordinary inlinefunction).
If the prohibition were relaxed to allow separate declaration anddefinition of constexpr member functions, some questions would need tobe answered, such as whether theconstexpr specifier mustappear on both declaration and definition (theinlinespecifier need not). If it can be omitted in one or the other, there'sa usability issue regarding the fact thatconstexpr impliesconst; theconst qualifier would need to bespecified explicitly in the declaration in whichconstexprwas omitted.
If the current restriction is kept, the library clauses shouldstate in an introduction that a non-defining declaration of aconstexpr member function should be considered “for expositiononly” and not literal code.
Notes from the September, 2008 meeting:
In addition to the original issues described above, thequestion has arisen whether recursive constexpr functionsare or should be permitted. Although they were originallydesired by the proposers of the feature, they were prohibitedout of an abundance of caution. However, the wording thatspecified the prohibition was changed during the reviewprocess, inadvertently permitting them.
The CWG felt that there are sufficient use cases forrecursion that it should not be forbidden (although a newminimum for recursion depth should be added to AnnexClause Annex B [implimits]). If mutual recursion is to beallowed, forward declaration of constexpr functions mustalso be permitted (answering the original question in thisissue). A call to an undefined constexpr function in thebody of a constexpr function should be diagnosed when theouter constexpr function is invoked in a context requiringa constant expression; in all other contexts, a call toan undefined constexpr function should be treated as anormal runtime function call, just as if it had been invokedwith non-constant arguments.
Proposed resolution (July, 2009):
Change Clause 7 [expr] paragraph 4 as follows:
If during the evaluation of an expression, the result is notmathematically defined or not in the range of representable values forits type, the behavior is undefined, unless such an expressionappears where an integral constant expression is required(7.7 [expr.const]), in which case the program isill-formed. [Note: most existing implementations of C++ignore integer overflows. Treatment of division by zero, forming aremainder using a zero divisor, and all floating point exceptions varyamong machines, and is usually adjustable by a libraryfunction. —end note]
Add the indicated text to 7.7 [expr.const] paragraph2:
...
an invocation of a function other than a constexpr function or aconstexpr constructor [Note: overload resolution (12.2 [over.match]) is applied as usual —end note];
a direct or indirect invocation of an undefined constexprfunction or an undefined constexpr constructor outside the definitionof a constexpr function or a constexpr constructor;
a result that is not mathematically defined or not in therange of representable values for its type;
...
Change 9.2.6 [dcl.constexpr] paragraph 1 as follows:
Theconstexpr specifier shall be applied only to thedefinition of an object,the declaration of afunction
,or function template, ortothedeclaration of a static data member of an effective literal type(6.9 [basic.types]).If any declaration of a function orfunction template has theconstexpr specifier, then all itsdeclarations shall contain theconstexprspecifier. [Note: An explicit specialization can differ fromthe template declaration with respect to theconstexprspecifier. —end note] [Note: functionparameters cannot be declaredconstexpr. —endnote] [Example:constexpr int square(int x); //OK, declarationconstexpr int square(int x) { // OK return x * x; }constexpr int bufsz = 1024; // OK, definition constexpr struct pixel { // error:pixel is a type int x; int y; constexpr pixel(int); // OK, declaration }; constexpr pixel::pixel(int a) : x(square(a)), y(square(a)) { } //OK, definition constexpr pixel small(2); // error:square not defined, sosmall(2) // not constant (7.7 [expr.const]), soconstexpr not satisfied constexpr int square(int x) { // OK, definition return x * x; } constexpr pixel large(4); // OK,square defined int next(constexpr int x) { // error, not for parameters return x + 1; } extern constexpr int memsz; // error: not a definition—end example]
Add a new section following 16.4.6.5 [member.functions]:
Implementations shall provide definitions for any non-definingdeclarations ofconstexpr functions and constructors within theassociated header files.
Add the following bullet to the list in Clause Annex B [implimits] paragraph 2:
Nested external specifications [1 024].
Recursive constexpr function invocations [512].
...
(This resolution also resolvesissue 695.)