Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reinterpret_cast from object to first member

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()?

like image 567
Arnaud Avatar asked Jun 03 '15 10:06

Arnaud


People also ask

How do you use reinterpret cast in C++?

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.

What does the reinterpret_cast operator do?

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

What types of conversions can be done with reinterpret_cast?

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)

Is cast from a pointer to an object type well defined?

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:


2 Answers

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.

like image 115
interjay Avatar answered Sep 28 '22 08:09

interjay


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.

like image 23
dlask Avatar answered Sep 28 '22 07:09

dlask