0

I'm using the Chipmunk physics engine for my C++ project.

Chipmunk has it's own vector, cpVect, which is nothing but a struct { double x, y; };

However I have my own operator overloaded Vector class in my project - and I'd like to use it just as a cpVect and vice-versa, without any conversions (my class Vector's only data fields are double x, y as well)

Currently I use this for implicit conversions (for argument passing, setting a Vector variable to a cpVect, etc.)

inline operator cpVect() { return cpv( x, y ); };
inline Vector( cpVect v ) : x( v.x ), y( v.y ) {}

This works for most things, but has a few problems - for example it isn't compatible for using arrays of the type Vector with cpVect arrays.

For that I currently have to do this:

Vector arrayA[123];
cpVect* arrayB = (cpVect*) arrayA;
  • Is it possible by some way to use my Vector as cpVect and vice-versa? Data is identical with both structures, mine only has additional methods.
Alfred
  • 3
  • 1

3 Answers3

2

So if I understand you, you have this:

class Foo
{
  double x, y;
};

class Bar
{
  double x, y;
};

...and you want pretened that a Foo is actually a Bar, right?

You can't -- not without evoking Undefined Behavior. No matter what you try, you will fall in to the great UB black hole.

  • if you try to use a union, you'll evoke UB when you assign to my_union.foo and read from my_union.bar
  • if you try to reinterpret_cast you'll evoke UB when to try to use the casted pointer
  • if you try to use a C-style cast, you'll have the same problems as above

The problem is this: Even though Foo and Bar look the same, they are not the same. As far as C++ is concerned, they are completely different types, totally unrelated to each other. This is a Good Thing, but it can also throw up some barriers that can seem to be artificial and arbitrary.

So, in order to do this without evoking UB, you need to convert. You could make this nearly automatic, by simply adding a couple facilities to Bar (which I presume to be the one you wrote, not the one from the library):

class Bar
{
public:
  Bar(const Foo& foo) : x(foo.x), y(foo.y) {}; // lets you convert from Foo to Bar
  Bar& operator=(const Foo& foo) { x = foo.x; y = foo.y; return * this; }

  operator Foo() const { Foo ret;  ret.x = x; ret.y = y; return ret; } // lets you convert ffrom Bar to Foo
private: 
  double x, y;
};

Which will let you go from Foo to Bar and back again with little or no code. Plus the compiler will optimize a lot of this away in release builds.

Community
  • 1
  • 1
John Dibling
  • 99,718
  • 31
  • 186
  • 324
  • He was trying to make the conversion from array to array (or at least `vec*` ) work as well as individual object conversions. +1 for showing precisely why it's UB. – Mark B Nov 19 '10 at 21:58
  • @Mark: He can't without converting. – John Dibling Nov 19 '10 at 22:01
  • I can, and I have already done it with (cpVect*) someArrayOfVector; – Alfred Nov 19 '10 at 22:11
  • 1
    @Alfred: then you are relying on undefined behavior doing a certian thing. it certianly is not safe, nor is it portable. – John Dibling Nov 19 '10 at 22:13
  • And **why** is it undefined behaviour if `Foo` and `Bar` are both PODs, especially with the same memory layout (so `offsetof(Foo,x) == offsetof(Bar,x)` and `offsetof(Foo,y) == offsetof(Bar,y)`)? If you believe this is UB, please explain why would it be, because I believe both unions and reinterpret casts have well-defined operation on basic types and POD types. – Kos Nov 20 '10 at 05:16
0

If both of those are simple PODs (no virtual functions etc), then a simple reinterpret_cast could save you here.

Kos
  • 70,399
  • 25
  • 169
  • 233
  • Disagree. The standard mentions that the result of a reinterpret cast is "implementation defined", which is *not* the same thing as "undefined" - see http://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior . – Kos Nov 20 '10 at 05:23
0

Derive yours from theirs and fix-up the problems? Seems simple enough to have 1000 traps. :)

JimR
  • 15,513
  • 2
  • 20
  • 26