This paper proposes a slightly different syntax, namely
if constexpr(cond)
statement1;
else
statement2;
The differences vs. P0128R1 are:
constexpr is placed before the condition, indicating that the
condition is evaluated as a compile-time constant.constexpr is not repeated before or after the
else; an else binds to the nearest preceding
if-statement as before (regardless of constexpr)return statements in a non-taken branch are ignored
for return type deduction
// P0128R1
constexpr if (cond)
statement1;
constexpr else constexpr if (cond)
statement2;
constexpr else constexpr if (cond)
statement3;
constexpr else
statement4;
Compare with the syntax proposed in this paper:
if constexpr (cond)
statement1;
else if constexpr (cond)
statement2;
else if constexpr (cond)
statement3;
else
statement4;
The proposed syntax was approved by EWG during the Jacksonville (2016-03) meeting of WG21.
The wording below incorporates initial feedback from CWG.
static_assert declarations in the non-taken
branch of a constexpr if is not proposed.
void f() {
if constexpr (false)
static_assert(false); // ill-formed
}
template<class T>
void g() {
if constexpr (false)
static_assert(false); // ill-formed; no diagnostic required for template definition
}
Change in 3.2 [basic.def.odr] paragraph 4:
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement (6.4.1 [stmt.if]); no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is odr-used outside of a discarded statement.Change in 6.4 [stmt.select] paragraph 1:
selection-statement:
if constexpropt ( condition ) statement
if constexpropt ( condition ) statement else statement
switch ( condition ) statement
See 8.3 [dcl.meaning] for the optional attribute-specifier-seq in a
condition. In Clause 6, the term substatement refers to the
contained statement or statements that appear in the syntax
notation. ...
Add a new paragraph after 6.4.1 [stmt.if] paragraph 1:
If the parenthesized condition is prefixed withChange in 7.1.6.4 [dcl.spec.auto] paragraph 2:constexpr, the value of the condition shall be a contextually converted constant expression of typebool(5.20 [expr.const]); this form is called a constexpr if statement. If the value of the converted condition is false, the first substatement is a discarded statement, otherwise the second substatement, if present, is a discarded statement. During the instantation of an enclosing templated entity, if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated. [ Note: Odr-uses (3.2 [basic.def.odr]) in a discarded statement do not require an entity to be defined. -- end note ] Acaseordefaultlabel appearing within such anifstatement shall be associated with aswitchstatement (6.4.2 [stmt.switch]) within the sameifstatement. A label (6.1 [stmt.label]) declared in a substatement of a constexprifstatement shall only be referred to by a statement (6.6.4 [stmt.goto]) in the same substatement. [ Example:template<typename T, typename ... Rest> void g(T&& p, Rest&& ...rs) { // ... handle p if constexpr (sizeof...(rs) > 0) g(rs...); // never instantiated with an empty argument list. } extern int x; // no definition of x required int f() { if constexpr (true) return 0; else if (x) return x; else return -x; }--- end example]
... If the declared return type of the function contains a placeholder type, the return type of the function is deduced from non-discardedChange in 7.1.6.4 [dcl.spec.auto] paragraph 7:returnstatements, if any, in the body of the function, if any(6.4.1 [stmt.if]).
When a variable declared using a placeholder type is initialized, or a non-discarded return statement occurs in a function declared with a return type that contains a placeholder type, the deduced return type or variable type is determined from the type of its initializer. ...Change in 7.1.6.4 [dcl.spec.auto] paragraphs 9-11:
If a function with a declared return type that contains a placeholder type has multiple non-discarded return statements, the return type is deduced for each return statement. If the type deduced is not the same in each deduction, the program is ill-formed.Change in 14.5 [temp.decls] paragraph 2 as follows:If a function with a declared return type that uses a placeholder type has no non-discarded return statements, the return type is deduced as though from a return statement with no operand at the closing brace of the function body. [ Example: ... ]
Once a non-discarded return statement has been seen in a function, however, the return type deduced from that statement can be used in the rest of the function, including in other return statements. ...
For purposes of name lookup and instantiation, default arguments and exception-specifications of function templates and default arguments and exception-specifications of member functions of class templates are considered definitions; each default argument or exception-specification is a separate definition which is unrelated to the function template definition or to any other default arguments or exception-specifications. For the purpose of instantiation, the substatements of aChange in 14.6 [temp.dep] paragraph 8:constexprifstatement (6.4.1 [stmt.if]) are considered definitions.
... If no valid specialization can be generated for a template or a substatement of aChange 14.7.1 [temp.inst] paragraph 11 as follows:constexprifstatement (6.4.1 [stmt.if]) within a template, andthatthe template is not instantiated, the template is ill-formed, no diagnostic required. ...
An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class,ora static data member of a class template, or a substatement of aconstexprifstatement (6.4.1 [stmt.if])that does not require instantiation, unless such instantiation is required.