
Steven wrote:
Even without overriding virtuals, technically such a cast is wrong. "If a nonstatic member function of a class X is called for an object that is not of type X, or of a type derived from X, the behavior is undefined." (9.3.1/1)
Ah, I see, because I am calling functions of the derived type on an object of the base type you believe that the behavior is undefined. This would be true if the derived type added data members or virtual pointer. In fact, I really struggled with the compiler's stubborn refusal to treat the derived type and the base type as equivalent when designing and implementing the design pattern. It really made me wish for features in that language that don't exist...yet. If I used composition, I would call a function of my composed type on an object of type X (by reinterpret_cast) and it also appears that the standard states that the behavior is undefined based upon your citation. This doesn't convince me that it isn't safe, just that it might not be safe, which we already knew.
reinterpret_cast at least guarantees reversibility, static_cast doesn't even do that. static_cast: "If the rvalue of type "pointer to cv1 B" points to a B that is actually a sub-object of an object of type D, the resulting pointer points to the enclosing object of type D. Otherwise, the result of the cast is undefined." (5.2.9/8)
My main issue is that you are relying on unspecified and/or undefined behavior to accomplish this. One possible solution is to store a
rather than a copy. This is problematic when you need a temporary
because you would need two types--one that stores a pointer and one
Yes, if the derived class adds virtual function pointer not present in the base class, or uses multiple inheritance its pointer value may differ from the address of the base class data enclosed within it. I think it is safe to say that we understand this fact and can design around it. Do you know of any other way the pointer values may be different? pointer though, that
can hold a value.
I don't for a minute believe that the behavior I am relying upon is unspecified or undefined. It is specified in the compiler, and all the compilers somehow managed to agree on the definition and specify it the same way. I would be quite surprised if it wasn't the standard that led to this remarkable standardization of C++ compiler front-ends. Perhaps the burden of proof falls upon me, but I don't think I should be considered wrong until proven right. The code works and is perfectly portable. I must have known something when I was designing it. Yes, almost any other solution for doing what I'm trying to do is problematic. It was very problematic to coax the compiler and language to do what I wanted them to. Translating the idea into legal syntax was quite challenging. Luke