And as for your argument that the compiler knows where n came from, there is nothing particularly difficult, tricky, or obscure about hiding the implementation of Person within its own translation unit in such a way that the compiler has no way of knowing that Person even has a member of type std::string. There is nothing undefined or even suspicious about the above program.
are you suggesting this is undefined behavior? Because it contains two pointers of distinct types, but they point to the same object and absolutely alias one another: #include į(&p, n) // &p has type Person*, n has type std::string*. There are certainly special cases where a compiler can prove it, like an int* is not allowed to alias a double*, but in general the compiler has to assume that pointers potentially alias one another.
In general there's no way to know if two pointers are aliasing one another. In that case the compiler would have no way of knowing that Bar contains a Foo and hence that a pointer to Bar can alias a pointer to Foo. They alias one another despite being different types.Įven if you want to argue that the compiler could "see" that Bar contains a Foo and hence would know about its layout, I could come up with a more sophisticated example by forward declaring Bar so as to hide its layout behind an opaque pointer. In the above, foo and bar are different types that point to the exact same object as per the standard (standard guarantees object layout). The following are two pointers of type Foo and Bar that point to the exact same object. The standard (note that I say the standard, not the implementations) says that if you send a function two pointers of type Foo and Bar, they are guaranteed to not be aliased (ie they point to different memory regions), and you have no guarantee if the pointers are of the same type.ĭon't see anywhere in the standard where it says that and don't see how that could even be true.