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];
}
Edit 1 (almost solution)
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?
Edit 2
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?
Edit 3 (Solution)
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