Post by Alexander Grigoriev"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 is a constant expression
(5.19), in which case the program is illformed.
[Note: 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. ]"
An arithmetic constant expression shall have arithmetic or
enumeration type and shall only have operands
that are integer literals (2.13.1), floating literals (2.13.3),
enumerators, character literals (2.13.2) and
sizeof expressions (5.3.3). Cast operators in an arithmetic constant
expression shall only convert arithmetic
or enumeration types to arithmetic or enumeration types, except as
part of an operand to the sizeof
operator.
This means: 1.f/0.f is a constant expression and the compiler is
evaluating it on compile time. Since it's not _mathematically_
defined (don't mind it's defined by IEC559), the program is illformed.
You almost had me convinced. As I understand your argument, the C++ standard
leaves the compiler implementer wriggle room (i.e., behaviour is undefined)
in handling mathematically undefined expressions provided they are not
constant expressions. To that extent, the compiler can conform with IEC 559
with regards to division by zero.
However, when dealing with constant expressions, there is no wriggle room
for mathematically undefined expressions (the program is ill-formed), so IEC
559 is irrelevant for a conforming implementation.
I note, however, that Comeau online compiles
float f (1.0f/0.0f);
without complaint.
On the other hand, it issues a warning for
float f(1/0);
So is Comeau non-conformant, or is something being missed here?
You refer to the standard but seem to have merged some passages. The 2003
standard says in section 5.19/1:
"An integral constant-expression can involve only literals (2.13),
enumerators, const variables or static data members of integral or
enumeration types initialized with constant expressions (8.5), non-type
template parameters of integral or enumeration types, and sizeof
expressions. Floating literals (2.13.3) can appear only if they are cast to
integral or enumeration types. Only type conversions to integral or
enumeration types can be used. In particular, except in sizeof expressions,
functions, class objects, pointers, or references shall not be used, and
assignment, increment, decrement, function-call, or comma operators shall
not be used."
Now, since the floating literals in 1.0f/0.0f are not cast to integral or
enumeration types, 1.0f/0.0f does not constitute an "integral
constant-expression".
There is another possibility: an "arithmetic constant expression". By 5.19/3
"An arithmetic constant expression shall satisfy the requirements for an
integral constant expression, except that
- floating literals need not be cast to integral or enumeration type,
- conversions to floating point types are permitted."
Thus 1.0f/0.0f is an "arithmetic constant expression". Is this the same as a
"constant expression" that would make the program ill-formed. Section 5.19/2
appears to give the answer:
"Other expressions [including arithmetic constant expressions] are
considered constant-expressions only for the purpose of non-local static
object initialization (3.6.2)."
In
int main()
{
float f (1.0f/0.0f);
}
f is not a non-local static object, so 1.0f/0.0f is not a "constant
expression" and therefore the program is *not* ill-formed.
By this reasoning, however,
float f (1.0f/0.0f);
int main()
{
}
is ill-formed. Comeau, however, compiles this program too, so I am still
puzzled.
--
John Carson