James Kanze
11/6/2008 8:51:00 AM
On Nov 5, 8:27 pm, aschep...@gmail.com wrote:
> Consider this compilation unit:
> struct Base {};
> struct A : public Base { int x; };
> struct B : public Base { int y; };
> int Base::*const px = static_cast<int Base::*>(&A::x);
> int Base::*const py = static_cast<int Base::*>(&B::y);
> bool f() {
> return px == py;
> }
> First, is the program ill-formed? Or is the behavior undefined?
> 5.10p2 says px == py "if and only if they would refer to the
> same member of the same most derived object (1.8) or the same
> subobject if they were dereferenced with a hypothetical object
> of the associated class type." I assume the "associated class
> type" here is Base. But 5.2.9p9 and 5.5p4 make it clear that
> dereferencing an object with dynamic type Base using px or py
> gives undefined behavior.
> If the above is ill-formed or undefined, does it follow that
> the expression (px == px) has the same problem?
I don't think that the standard is really clear about this. All
of the statements until the == are well formed and fully
defined. The return statement with the == is also well formed,
but I'm not sure what the results are supposed to be. It's not
clear here what the "associated class type" is; if you read this
to mean that your px == py is semantically equivalent to
&someBObject.x == &someBObject.y, then you have a real problem,
because of course, that expression won't even compile; if you
replace the "someBObject."s with "ptrToSomeBObject->", then your
code would have undefined behavior. Which, I suspect, is
probably the intent (if one can speak of "intent" about a case
which was apparently not considered); any time the standard
doesn't define a specific behavior, the behavior is undefined.
(In this case, it would seem reasonable to have the results
unspecified, rather than the behavior undefined, but in
practice, I doubt that changes anything for real programs.)
> Not too surprisingly, my compiler has the above f() return
> true. If this happens, it seems reasonable to assume that the
> following also always returns true, although the a.*py is
> technically at best undefined:
> bool g( A& a ) {
> return &(a.*py) == &a.x;
> }
If the comparison is undefined behavior, then you can't count on
anything. Until proof of the contrary, I think that this is
what you have to assume.
> Realistically, it seems like I can count on the "logic" that
> f() implies g(), even though the Standard doesn't technically
> guarantee this.
I don't think so. It's quite possible for a compiler to include
type information in a pointer to member, which would invalidate
your assumptions.
> But if any of this is ill-formed, I want to avoid it.
Not ill-formed, but undefined behavior is probably something you
should avoid as well.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34