3

I'm talking about tens of members, so I would really avoid something like creating a conversion function that copies everything one by one.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Ioana
  • 343
  • 5
  • 10
  • 1
    Why do you have two identical structures in the first place? – jrok Jun 30 '13 at 15:02
  • Do you have anything `virtual` in them or base classes or contents? Any references? Any destructors in them or their contents or their base classes? How portable need this be? Do you own one or the other classes definition and can change them? Is everything public? Can you change how they are used? – Yakk - Adam Nevraumont Jun 30 '13 at 15:05
  • assuming 100% identical layout ClassA* a = reinterpret_cast(b) will allow you to create a pointer of type ClassA to an instance of ClassB. dangerous and brittle – dkackman Jun 30 '13 at 15:06
  • If for some reason the same structure serves two different purposes and it's beneficial to refer to it by two (or more) different names, why not create typedefs for all the names? – neuviemeporte Jun 30 '13 at 15:59

4 Answers4

5

The best thing to do is to solve the issue by not having this redundancy at all. This is not DRY.

A trivial solution which I am sure you cannot apply (otherwise you had already done that), would be to move the common syntax of the two types to a base class and separate the semantic differences into two derived (probably empty) classes.

If this is not achievable, you could use an adapter class to encapsulate any of the two Types that you have and access them both with the same interface.

Obj2 o2;
Adapter<Obj2> a(o2);
a.getFirstMember();

Reinterpreting a pointer to one object as a pointer to the the other one is also possible:

Obj1 *p = reinterpret_cast<Obj1 *>(&obj2);

but the two objects really need to have the same memory footprint e.g., for any possible value of any member, replicated in both the types, the following must always be true:

memcmp(&obj1, &obj2, sizeof(Obj1)) == 0 && sizeof(obj1) == sizeof(obj2)

This is generally hard to guarantee and it can become even more non-trivial if the compiler will add something for you in one of the two classes (an innocent refactoring in a couple of months time may easily bring this problem in).

Think for example to a virtual destructor. If you have it in one class (as the only virtual member) and not in the other, then that one class will have a vptr as its first member and the other one will not, so accessing that offset in both classes will yield different results.

Vincenzo Pii
  • 18,961
  • 8
  • 39
  • 49
  • 1
    Even with identical object layout, dereferencing the result of that `reinterpret_cast` is undefined behavior due to aliasing violation. – Cubbi Jun 30 '13 at 16:20
  • 1
    @Cubbi Thanks for pointing this out. More information: http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule – Vincenzo Pii Jun 30 '13 at 16:26
  • Thank you, I will check out this reinterpret_cast thing. Since everyone is wondering why I have 2 identical declarations, the thing is that I am rewriting a really big library in order to improve it, and since this will take some time and I am gradually removing their declarations, I want to be able to temporarily have things like my_function(my_variable)=their_function(their_variable), where my_variable and their_variable have different names but are actually identical structures. – Ioana Jul 01 '13 at 23:32
3
  1. You shouldn't have two data types with exactly identical members but different names. It's just redundant code, try to get rid of the redundant types.
  2. If for some reason you cannot(really hard to believe you cannot) simply use reinterpret_cast to cast one type to another.

Note that the class/structure need to be exactly identical w.r.t its composition and not not have any virtual members.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
1

Use the keyword union. It is not brittle.

I ran into the need for this when writing a game engine using D3D11X library items along with DirectX10. If you have, for instance, a vector (3 floats) and you don't want to have to cast it to a D3D11X_vector or a DX11_vector or whatever, you can create a struct that is a union of both. (Sometimes, like for graphics drivers, the code is not yours and you cannot change anything below the boilerplate.)

https://msdn.microsoft.com/en-us/library/5dxy4b7b.aspx

Matt
  • 11
  • 1
0

No there is no other way then to create a function from one to the other, and this is the most logical thing to do anyways. Perhaps you could write a macro that would iterate over the fields somehow... but what would be the point? This will just make the code more unstable and hard to understand. If each field is exactly the same type and they are in the same order, then perhaps you could just cast from one to the other, but I'd still avoid that.