I was looking at this answer and I was wondering if casting an object to its first member with reinterpret_cast and using the result could be safe in C++.
Let's assume that we have a class A, a class B and an instance b of B:
class A{
public:
int i;
void foo(){}
};
class B{
public:
A a;
};
B b;
Question 1: Is it safe to use b.a like this: reinterpret_cast<A*>(&b)->foo()
?
Note: In the general case we suppose that the class and its member are both standard layout.
My lecture of the available references on reinterpret_cast tells me such usage should be authorized as there is no aliasing violation, however it conflicts with many answers like this one.
Question2: Is it safe to use b.a like this: static_cast<A*>(static_cast<void*>(&b))->foo()
?
reinterpret_cast in C++ | Type Casting operators. reinterpret_cast is a type of casting operator used in C++. It is used to convert one pointer of another pointer of any type, no matter either the class is related to each other or not. It does not check if the pointer type and data pointed by the pointer is same or not.
The reinterpret_cast operator produces a value of a new type that has the same bit pattern as its argument. You cannot cast away a constor volatilequalification. You can explicitly perform the following conversions: A pointer to any integral type large enough to hold it A value of integral or enumeration type to a pointer
Only the following conversions can be done with reinterpret_cast, except when such conversions would cast away constness or volatility . 1) An expression of integral, enumeration, pointer, or pointer-to-member type can be converted to its own type. The resulting value is the same as the value of expression. (since C++11)
If the implementation provides std::intptr_t and/or std::uintptr_t, then a cast from a pointer to an object type or cv void to these types is always well-defined. However, this is not guaranteed for a function pointer. Demonstrates some uses of reinterpret_cast:
Yes, because both classes here are standard-layout types, you can convert between &b
and &b.a
.
reinterpret_cast<A*>(p)
is defined to be the same as static_cast<A*>(static_cast<void*>(p))
, (5.2.10p7) so both your questions are equivalent.
For standard-layout classes, the address of the struct/class is the same as the address of its first non-static member (9.2p19). And static_cast
to/from void*
will preserve the address (5.2.9p13), meaning the result will be valid.
If the classes were not standard-layout, you could not rely on this behavior.
Formal answer: Yes, there are situations when you can do that (see the answer of @interjay).
Practical answer: Please don't do that. Really. Mainly when the straight path is available:
b.a.foo();
In other words, don't use typecasts if there is at least a minimal chance to avoid them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With