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:
- 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."
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.