
From: Simonson, Lucanus J
Martin wrote:
I don't think that's true. Given: class Base {....} struct Derived : public Base{ int DerivedFunction(); };
Base b; Derived* pDerived = static_cast<Derived*>(&b);
pDerived->DerivedFunction(); // Undefined behaviour. The behaviour of the call to DerivedFunction is not defined by the standard. (Of course, on many compilers today it will do what the author >expected.)
The reason it is categorized as undefined is because Derived may extend Base by adding data members, inheriting from another base, or adding a virtual pointer. Partly My contention was that the behavior when none of those conditions is true is defined, or at least implicitly defined. What I mean by implicitly defined is that if X is true, and Y is true then we can infer that Z must also be true. This happens in specs all the time.
You missed my point about type aliasing. Let's extend the example a little further (and convert to references because that's what you tend to use). struct Base { int i; }; struct Derived : Base { void f() { this->i = 5; } }; Base b; b.i = 2; Derived &refD = static_cast<Derived&>(&b); refD.f(); b.i -= 2; At this point a compiler which does value tracking "knows" that b.i is 2 (not 5) and can optimize the last statement to b.i = 0; With most compilers today, that only works because Derived.f() is inline, and the compiler can see that there is no cast of refD to Base&. Future compilers may be better at optimizing between modules.
If I have Base and Derived types the compiler has to ensure correct execution when given the clearly standard compliant usage:
Derived object; object.do_something(); Base& baseRef = object; base.do_something_else(); Derived& derivedRef = static_cast<Derived&>(baseRef); derivedRef.do_yet_a_third_thing();
ergo it must implicitly support:
Base base; base.do_something_else(); Derived& derivedRef = static_cast<Derived&>(base); derivedRef.do_yet_a_third_thing();
provided that Derived does not modify Base by multiple inheritance, adding a member or a virtual pointer, because it can't prove that derivedRef is not an alias for the pointer to base because it could be that derivedRef is an alias for baseRef as part of the standard compliant usage.
Well yes it CAN prove that derivedRef is not an alias for baseRef in your second example - it can /see/ that derivedRef is not an alias for baseRef.
If a compiler optimization can be proven to break standard compliant code it is safe to assume that such compiler optimization won't happen, or at least will be rolled back immediately.
but how about a compiler optimization that /won't/ break standard compliant code, but /will/ break your code? -- Martin Bonner Senior Software Engineer/Team Leader PI SHURLOK LTD Telephone: +44 1223 441434 / 203894 (direct) Fax: +44 1223 203999 Email: martin.bonner@pi-shurlok.com www.pi-shurlok.com disclaimer