Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safety of casting between pointers of two identical classes?

Let's say I have two different classes, both represent 2D coordinate data in the same internal way like the following:

class LibA_Vertex{
    public:
    // ... constructors and various methods, operator overloads
    float x, y
};

class LibB_Vertex{
    public:
    // ... same usage and internal data as LibA, but with different methods
    float x, y
};


void foobar(){
    LibA_Vertex * verticesA = new LibA_Vertex[1000];
    verticesA[50].y = 9;
    LibB_Vertex * verticesB = reinterpret_cast<LibB_Vertex*>( vertexA );
    print(verticesB[50].y); // should output a "9"
};

Given the two classes being identical and the function above, can I reliably count on this pointer conversion working as expected in every case?

(The background, is that I need an easy way of trading vertex arrays between two separate libraries that have identical Vertex classes, and I want to avoid needlessly copying arrays).

like image 845
Anne Quinn Avatar asked Oct 14 '11 04:10

Anne Quinn


3 Answers

C++11 added a concept called layout-compatible which applies here.

Two standard-layout struct (Clause 9) types are layout-compatible if they have the same number of non-static data members and corresponding non-static data members (in declaration order) have layout-compatible types (3.9).

where

A standard-layout class is a class that:

  • has no non-static data members of type non-standard-layout class (or array of such types) or reference,
  • has no virtual functions (10.3) and no virtual base classes (10.1),
  • has the same access control (Clause 11) for all non-static data members,
  • has no non-standard-layout base classes,
  • either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and
  • has no base classes of the same type as the first non-static data member.

A standard-layout struct is a standard-layout class defined with the class-key struct or the class-key class.

A standard-layout union is a standard-layout class defined with the class-key union.

Finally

Pointers to cv-qualified and cv-unqualified versions (3.9.3) of layout-compatible types shall have the same value representation and alignment requirements (3.11).

Which guarantees that reinterpret_cast can turn a pointer to one type into a pointer to any layout-compatible type.

like image 188
Ben Voigt Avatar answered Nov 05 '22 01:11

Ben Voigt


I would wrap that conversion up in a class (so that if you need to change platform or something, it's at least localised in one spot) but yes it should be possible.

You'll want to use reinterpret_cast, not static_cast as well.

like image 37
Ayjay Avatar answered Nov 05 '22 03:11

Ayjay


Theoretically this is an undefined behavior. However, it may work in certain systems/platforms.

I would suggest that you should try to merge 2 classes into 1. i.e.

class Lib_Vertex{
// data (which is exactly same for both classes)
public:
// methods for LibA_Vertex
// methods for LibB_Vertex
};

Adding methods into a class will not affect its size. You may have to change your design a bit but it's worth it.

like image 1
iammilind Avatar answered Nov 05 '22 01:11

iammilind