Ah, another language issue. I read it as "adopt all C++'s const rules
and, as a result, avoid breaking any existing code" (which won't work)
whereas you read is as "adopt some of C++'s const rules and, in so
doing, avoid breaking existing code" which is, as you say, possible.
More accurately, I had a very good idea of precisely which C++ rules he
was talking about, from context. It's the "constant expression" rule
that is relevant, not the const rules. Also, a very large portion of the
texts of that rule in the C++ standard refers to various features of C++
that aren't relevant in a C context. Every aspect of those rules that's
relevant to the issues raised in this thread is included in my previous
message; nothing else is needed or, IMO, desirable.
Note: I had to split that one rule into two separate rules when adapting
it to C. That's because the C++ standard defines an integral constant
expression (ICE) as a constant expression of integral or enumeration
type, while C defines an integer constant expression (ICE) without
reference to the definition of constant expressions. However, the two
definitions match very closely. The only example I could come up with of
a constant expression of integer type that in not an ICE was
(int)(float)3, which is disqualified because of the (float) cast. If
I'm right, it would simplify things to define an ICE as a constant
expression of integer type, similar to the way C++ defines them. I'm no
big fan of expressions like "(int)(float)3", but allowing them to be
constant expressions while excluding them from being ICEs involves 5
lines of complicated redundant text to the standard. I wonder how many
compilers get that issue right?
One aspect of the C++ constant expression rules bothers me, and I
"corrected" it when restating it for a C context. Given
const int i = 30;
const double d = 30.0;
If I'm reading the C++ rules correctly, then i and 30 are both integer
constant expressions. The expressions i, 30, and 30.0 are all constant
expressions, but d is not. The relevant part of 5.19 allows
lvalue-to-rvalue conversions in constant expressions only when they have
integral and enumeration type (ignoring some C++-specific exceptions).
The C standard doesn't use the phrase "lvalue-to-rvalue conversion",
though the thing described by that phrase does occur in C. Also, it uses
"integer" instead of "integral", and "enumerated type" instead of
"enumeration type", and in C, enumerated types qualify as integer types,
so if it were desired to duplicate that restriction in C, it would be
simplified to "integer type" - but I don't see the need for such a
restriction.