Mat
Mat

Reputation: 4501

c++ how to define cast operator that doesn't copy data?

okay - maybe this is a silly question and cast operators do this already inherently..

What I have:

both classes interally simply store a float[16];

i'd like to define in my Matrix class a cast operator so that I can do things like:

MyMatrix4x4 m;
OtherMatrix4x4(m).someFunctionDefinedInOtherMatrix4x4();
SomeFunctionThatTakesOtherMatrix4x4(OtherMatrix4x4(m));

And I don't want this operator to copy any data - the functions should simply operate on the same float[16] data

How to do that?

Upvotes: 1

Views: 2178

Answers (3)

Alex
Alex

Reputation: 5439

Just to present a different solution presenting inheritance. These would allow the use of code you posted above. However this is not a cast operator.

class MyMatrix4x4 {
public:
    float f;
};

class OtherMatrix4x4 : MyMatrix4x4  {
public:
    OtherMatrix4x4(MyMatrix4x4 &matrix)
    {
        f = matrix.f;
    }

    void someFunctionDefinedInOtherMatrix4x4();
};

Upvotes: 0

Nicol Bolas
Nicol Bolas

Reputation: 473407

And I don't want this operator to copy any data - the functions should simply operate on the same float[16] data

I don't want to create any data on the heap. want this to work with values on the stack - and also for convenciance i'd like to have a cast operator

Well that's not going to happen. C++'s aliasing rules pretty much forbid that.

You can use pointer-casts to do "pretend this is something else", but you can't use object casts to do that. You could cast a pointer to a stack object to a pointer to your type of object:

MyMatrix4x4 m;
OtherMatrix4x4 * o = (OtherMatrix4x4 *) &m;

However, there are two problems. First, o will last only as long as m does. It isn't an object; it's a pointer to a different object. Second, doing this is (in general) undefined behavior (in part due to violating aliasing: two unrelated types overlapping). Oh, odds are that it will work. But you're off the map as far as what C++ will guarantee.

This smells of a premature optimization. Do you really think that copying 16 floats is that big of a performance issue? If it is, then why not just use OtherMatrix4x4 in your code instead of MyMatrix4x4?

Upvotes: 3

Luchian Grigore
Luchian Grigore

Reputation: 258598

OtherMatrix4x4(m)

This isn't a cast operator, it's a conversion constructor.

Suppose the following definition of MyMatrix4x4:

struct MyMatrix4x4
{
    float x[16];
};

The the following should do it:

struct OtherMatrix4x4
{
    float* x;
    OtherMatrix4x4(MyMatrix4x4& other)
    {
       x = other.x;
    }
    void foo()
    {
       x[0] = 0;
    }
};

To test:

MyMatrix4x4 a = {{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}};
OtherMatrix4x4(a).foo();
cout << b.x[0]; //will output 0, not 1

EDIT Here's the version where you cant edit the other matrix:

struct OtherMatrix4x4
{
    float x[16];
    void foo()
    {
        x[0] = 0;
    }
};

struct MyMatrix4x4
{
    float* x;
    operator OtherMatrix4x4()
    {
        OtherMatrix4x4 other;
        x = other.x;
        return other;
    }
};

MyMatrix4x4 m;
OtherMatrix4x4(m).foo();

Upvotes: 1

Related Questions