clanguage-lawyerevaluationconstant-expressionexpression-evaluation

Why "Each constant expression shall evaluate to..." instead of "Each evaluated constant expression shall evaluate to..."?


n3301, 6.6 Constant expressions, p4 (emphasis added):

Each constant expression shall evaluate to a constant that is in the range of representable values for its type.

n3301, 6.5.15 Logical OR operator, p4 (emphasis added):

If the first operand compares unequal to 0, the second operand is not evaluated.

Question: why the 1st requirement does not depend on the requirement of evaluation (or non-evaluation) of such constant expression?

In other words: why "Each constant expression shall evaluate to..." instead of "Each evaluated constant expression shall evaluate to..."?

Is this an oversight?


Reason of the question: some people believe that "Each constant expression shall evaluate to..." takes precedence (i.e. stronger, has more priority) over the "second operand is not evaluated".

Yes, the n3301 has footnote 119:

  1. Thus, in the following initialization,
static int i = 2 || 1 / 0;

the expression is a valid integer constant expression with value one.

However, "In ISO standards, notes are without exception non-normative."


Solution

  • The quote at issue is part of the definition of constant-expression, the grammar rule is used in places where code is expected to be evaluated at compile-time. This means that constant-expression are usually evaluated unconditionally (at compile-time). Introducing the concept of a constant-expression that isn't evaluated is unhelpful and unnecessary.


    2 || 1 / 0 is a valid constant-expression because it's a valid conditional-expression that meets the constraints of constant-expression.

    Relevantly, it evaluates to 1, so it does "evaluate to a constant that is in the range of representable values for its type."

    Evaluating 2 || 1 / 0 doesn't evaluate 1 / 0, but that doesn't mean that 2 || 1 / 0 can't be evaluated.

    Therefore, 2 || 1 / 0 can be used where a constant-expression is expected. For example, case 2 || 1 / 0 is valid (although quite odd).

    Demo on Compiler Explorer.


    While 1 / 0 is a valid conditional-expression, it doesn't meet the constraints of constant-expression, so it's not a valid constant-expression.

    Specifically, it doesn't "evaluate to a constant that is in the range of representable values for its type."

    Therefore, 1 / 0 can't be used where a constant-expression is expected. For example, case 1 / 0 is invalid.

    Demo on Compiler Explorer.