Reputation: 1057
I want to do something like this:
Matrix m; // (4x4 matrix)
Vector4 v; // (4-elements vector)
m(0) = v; // replace first 4-elements matrix row by vector v
v = m(0); // replace vector v by first 4-elements matrix row
heres my code:
Vector4& Matrix::operator() (unsigned row)
{
return Vector4(mat[row][0], mat[row][1], mat[row][2], mat[row][3]);
}
Vector4 Matrix::operator() (unsigned row) const
{
return Vector4(mat[row][0], mat[row][1], mat[row][2], mat[row][3]);
}
the second operator works fine, but when I try to compile first one, I get this error:
error: invalid initialization of non-const reference of type ‘Vector4&’ from an rvalue of type ‘Vector4’
So where is the problem? It's good idea to overload operator() instead of operator[] in this case?
By getting only one element from matrix I use the other two operators:
float& Matrix::operator() (unsigned row, unsigned col)
{
return mat[row][col];
}
float Matrix::operator() (unsigned row, unsigned col) const
{
return mat[row][col];
}
I think I found some solution. The first operator has been replaced to:
Matrix::MatrixHelper operator() (unsigned row)
{
MatrixHelper m;
m.f1 = &mat[row][0];
m.f2 = &mat[row][1];
m.f3 = &mat[row][2];
m.f4 = &mat[row][3];
return m;
}
heres the definition of MatrixHelper class:
class MatrixHelper
{
public:
friend class Matrix;
void operator= (const Vector4& v)
{
*f1 = v.x;
*f2 = v.y;
*f3 = v.z;
*f4 = v.w;
}
private:
float* f1;
float* f2;
float* f3;
float* f4;
};
now is possible to do something like that:
m(0) = Vector4(3,3,3,3);
but then occurs new problem, when calling this:
(m)(0) * someScalar;
the second operator is never called, so I have to implement them in my MatrixHelper class right? I'm on the right track?
OK this problem would be solved if the two operators would be working at the same time. But now only one of them can be enabled. I can not understand why always is working the first operator, for example having this code (just example):
Vector4& Matrix::operator() (unsigned row)
{
std::cout << "Operator one is working now\n";
}
Vector4 Matrix::operator() (unsigned row) const
{
std::cout << "Operator two is working now\n";
}
No matter if I am doing
m(0) = Vector(4,4,4,4)
or
Vector4 v = m(0)
always is working the first operator. Why?
I have found some other solution. Now all it's working, but performance may be a little problem. Solution not resolved in the way I wanted and it is a little far-fetched. Here's the code:
Operators:
Vector4 Matrix::operator() (unsigned row)
{
return Vector4 (&mat[row][0], &mat[row][1], &mat[row][2], &mat[row][3]);
}
Vector4 Matrix::operator() (unsigned row) const
{
return Vector4 (mat[row][0], mat[row][1], mat[row][2], mat[row][3]);
}
as you can see the first operator returns a vector that takes pointers. The hard work happens now in Vector4 class instead of Matrix. Vector4 has now an extra constructor:
Vector4(float* x, float* y, float* z, float* w)
{
this->px = x; this->py = y; this->pz = z; this->pw = w;
this->x = *x; this->y = *y; this->z = *z; this->w = *w;
pointer = true;
}
first line are pointers, second - variables, and third line is a boolean type variable witch means what constructor has been called (normal or pointers).
Now comes the last operator (operator=):
Vector4 operator= ( const Vector4& v)
{
if ( pointer )
{
*px = x = v.x;
*py = y = v.y;
*pz = z = v.z;
*pw = w = v.w;
}
else
{
x = v.x;
y = v.y;
z = v.z;
w = v.w;
}
}
If pointer
is true that means - px
, py
, pz
and pw
are pointers to some row elements in matrix, and we have to change them. Else - just normal vector.
So now question... it is bad bad solution, or just bad? :D
Upvotes: 2
Views: 834
Reputation: 793
The Vector4
you are instantiating in the errored code is an r-value which is temporary. Aside from the fact that you can't assign it to a non-const reference, it will be destroyed when your function exits and the return value would be an invalid stack location.
One solution would be to return a different object by value that stores references to the individual elements you need and allows you to act upon them in a transparent way.
Upvotes: 2