Question

I'm using two different libraries in my project, and both of them supply a basic rectangle struct. The problem with this is that there seems to be no way to insert a conversion between the types, so I can't call a function in one library with the result from a function in the other. If I was the author of either of these, I could create conversions, from the outside, I can't.

library a:

typedef struct rectangle { sint16 x; sint16 y; uint16 w; uint16 h; } rectangle;

library b:

class Rect {
  int x; int y; int width; int height;
  /* ... */
};

Now, I can't make a converter class, because C++ will only look for a conversion in one step. This is probably a good thing, because there would be a lot of possibilities involving creating new objects of all kinds of types.

I can't make an operator that takes the struct from a and supplies an object of the class from b:

foo.cpp:123 error: ‘operator b::Rect(const rectangle&)’ must be a nonstatic member function

So, is there a sensible way around this?

edit:

I should perhaps also point out that I'd really like some solution that makes working with the result seamless, since I don't expect to be that coder. (Though I agree, old-school, explicit, conversion would have been a good choice. The other branch, reinterpret_cast has the same problem..)

edit2:

Actually, none of the suggestions really answer my actual question, Konrad Rudolph seems to be correct. C++ actually can't do this. Sucks, but true. (If it makes any difference, I'm going to try subclassing as suggested by CodingTheWheel.

Was it helpful?

Solution

If you can't modify the structures then you have no alternative to writing a manual conversion function because overloading conversion operators only works within the class body. There's no other way.

OTHER TIPS

Create an intermediate shim type "RectangleEx", and define custom conversions to/from the 3rd-party string types. Whenever you speak to either API, do so through the shim class.

Another way would be to derive a class from either rect or Rectangle, and insert conversions/constructors there.

Not sure how sensible this is, but how about something like this:

class R
{
public:
    R(const rectangle& r) { ... };
    R(const Rect& r) { ... };

    operator rectangle() const { return ...; }
    operator Rect() const { return ...; }

private:
    ...
};

Then you can just wrap every rectangle in R() and the "right thing" will happen.

It may not be feasible in your case, but I've seen people employ a little preprocessor-foo to massage the types into compatibility.

Even this assumes that you are building one or both libraries.

It is also possible that you don't want to do this at all, but want to re-evaulate some early decision. Or not.

Why not something simple like this: (note this may/probably won't compile) but you get the idea...


private Rect* convert(const rectangle& src)
{
    return new Rect(src.x,src.y,src.w,src.h);
}
int main()
{
    rectangle r;
    r.x = 1;
    r.y = 2;
    r.w = 3;
    r.h = 4;

    Rect* foo = convert(&r);
    ...
    delete foo;

}

EDIT: Looks like koko's and I have the same idea.

If the structs were the same internally, you could do a reinterpret_cast; however, since it looks like you have 16-bit vs 32-bit fields, you're probably stuck converting on each call, or writing wrappers for all functions of one of the libraries.

Maybe you could try it with operator overloading ? (Maybe a = operator which is not a method of your class) ?

Rect operator= (const Rect&,const rectangle&)

More about this in the C++ programming language by Bjarne Stroustrup or maybe on this page: http://www.cs.caltech.edu/courses/cs11/material/cpp/donnie/cpp-ops.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top