I really don't think that is indeed the case, if the cast can be done
at compile time
like in
const int x = 5.5;
I don't consider that a "cast"; that's just a conversion. By "cast", I mean
either
(type) expression
type (expression)
or new-style_cast<type>(expression)
and I'm saying you can't make the result of one of those be the left
operand of an assignment operator (or ++/--).
then there is no need to produce a temporary.
Right, because it isn't a "cast".
I am not sure what you mean by "not assignable" do you mean that they
can't be an lvalue.
That's probably better wording, or "not modifiable" perhaps. I began trying
to elaborate on this based on what the Standard says; I've been bouncing
around between 3.10/2, 3.10/6 and writing test programs, and finally
decided I just don't understand some of the subtleties enough to really
follow through with an analysis.
I do, however, have a pet theory as to what the default MSVC 7 behavior is
doing, even though I haven't a clue why Microsoft would find such behavior
to be useful. In the strange behavior, the call
foo ((const int) x);
results in the function call argument being bound to a reference to
non-const (the function parameter). Here's what section 3.10/6 has to say
about the result of casts:
"An expression which holds a temporary object resulting from a cast to
a nonreference type is an rvalue (this includes the explicit creation
of an object using functional notation (5.2.3))."
My suspicion is that the strange behavior is ignoring this rule, and
retaining all the lvalue-ness of the cast's operand. Thus it behaves as we
see when the operand is an lvalue, but not when it is a constant. Consider
this expansion of the original example:
#include <iostream>
void foo(int& x) {std::cout << "In non-const foo\n"; }
void foo(const int& x) { std::cout << "In const foo\n"; }
int main(void)
{
int x = 23;
foo(5);
foo(x);
foo( (const int ) x );
foo( (const int ) 5 );
return 0;
}
The output is:
In const foo
In non-const foo
In non-const foo
In const foo
The third one is the strange one, and can be explained by imagining that
the cast isn't actually producing a "new" temporary value, but rather is
passing the original operand x "as if" it had the desired type. The last
example shows that if you start with a constant (5), it doesn't magically
turn into an lvalue (which is a good thing.)
Another shot in the dark: perhaps Microsoft is interpreting 3.10/6's use of
the term "nonreference" to mean that, when the argument can be bound to a
(non-const) reference in the function call, the result of the cast is no
longer a "nonreference type" and thus exempt from the requirements of being
an rvalue. But if /Za is used, it battens down the hatches. I just have no
idea.
For what it's worth.
-leor