To me it is quite important to allow passing a reference to the zero object, in case you want to make Matrices of objects whose Zero element is not known in compile time. For example, you might want to make a matrix of Matrices. In this case, if you use variable # of columns& rows, the Zero matrix is not known at compile time - it will have a variable number of rows and columns.
[Edit:] On the first post I misread therockon7throw's suggestion.
His suggestion is the best way to solve the problem. It calls a theoretically non-necessary copy constructor; this is a well-known issue with operator overloading in C++; as far as I know, there is no workaround for it in the current C++ standard (is it going to be fixed in the new coming standard?).
@therockon7throw
Returning a reference to an object allocated on the stack is a very bad idea; it will introduce very-hard to catch bugs.
Matrix<T, COLS, ROWS> Matrix<T, ROWS, COLS>::operator~()
Maybe the return type as reference is an error.
At the very least it is a very bad design decision. Users of operator~ would have to delete the matrix you created for them manually. This is 1) counter-intuitive 2) you will certainly forget to do it at least once 3) every user other than yourself will fail to do it 4) any failure to release your memory will introduce a memory leak, which might stay in your code for years without being caught.
template<typename T, int ROWS, int COLS>
Matrix<T, ROWS, COLS>& Matrix<T, ROWS, COLS>::operator=(const Matrix<T, ROWS, COLS>& cp) {
_elements.clear();
for (int i = 0; i < cp._cols * cp._rows; i++)
_elements.push_back(cp(i));
return *this;
}
You said I don't need this operator and neither to do _elements.clear();
I think you was thinking with _elements = cp._elements;
In this way is true, I don't need to clear because it's implicit. But note that _elements is private so I can't do it.
Then, I think it's necessary to clear it. Am I wrong?
the code above should first create a new object by using the copy constructor of your class and than apply the operator *= on the new created object, and finally returnthe result.
So you are right your code is not changing the current object, this
It calls a theoretically non-necessary copy constructor; this is a well-known issue with operator overloading in C++; as far as I know, there is no workaround for it in the current C++ standard (is it going to be fixed in the new coming standard?).
There is a smart way to solve the problem and to eliminate creating and destroying the temporary objects. It is meta-programming, with C you can write programs, however with C++ you can do a higher degree of prgramming, manipulating programs :-) You can write program thats manipulate code or generates code in compile time, so you are able to avoid creating and destroying temporary objects, which results speed at run time and use of less physical memory.
template<class rep >
struct transpose;
template<typename T, int ROWS, int COLS>
class Matrix {
// do some thing
public:
typedef T value_type;
typedefunsignedint size_type;
//do some other things
// you should also implement a copy constructor for the same type
Matrix<T, ROWS, COLS >& operator=(const transpose< Matrix<T, ROWS, COLS > >& o)
{
for(unsigned i = 0; i < _rows; i++)
for (unsigned j = 0; j < _cols; j++)
this->operator()(i,j) = o(i,j);
return *this;
}
// do some other thing
// you may overload operator ! to get transpose of the matrix
transpose< Matrix<T, ROWS, COLS > > operator!(){
return transpose< Matrix<T, ROWS, COLS > >(*this);
}
};
You said I don't need this (assigment) operator and neither to do _elements.clear();
I think you was thinking with _elements = cp._elements;
In this way is true, I don't need to clear because it's implicit. But note that _elements is private so I can't do it.
¿Have you tried it?
In c++ you can touch private members from:
_ Yourself
_ Your friends
_ Your same kind
The copy will be simply elements = b.elements;, but the default assignment operator already does that.
However, just notice that you've got constunsigned _rows, _cols; (that will break it as they are not assignable). Get rid of those variables, you don't need them. That info is stored in the template parameters.
The copy will be simply elements = b.elements;, but the default assignment operator already does that.
You are totally right, elements is type of vector, so you dont have to worry about how they are copied, just leave it to the vector his self. vector must care how he copies or assigns his objects :-)
@ Aikon
So you dont need any copy or assignment for the object of your class itself, as ne555 said the default ones do their jobs well.
I think I almost understood your suggestion: you eliminate the unnecessary copying by using the mechanics of copy constructors and smart templating. This is very smart, however it is also very complicated (on the edge of my understanding).
I prefer waiting for a change in the standard to allow a simpler solution, rather than use your smart trick. In the meantime, if I am pressed for speed (which, in fact, I often am), I will just avoid the use of operator+ and use instead operator+= and thus micro-manage the copy constructors by hand.
I prefer waiting for a change in the standard to allow a simpler solution, rather than use your smart trick. In the meantime, if I am pressed for speed (which, in fact, I often am), I will just avoid the use of operator+ and use instead operator+= and thus micro-manage the copy constructors by hand.
You do not need to wait for the standard, they may never change it the way you expect them to.
you can overload all operator( + , - , *, / ++, -- or whatever else) by using expression template the smartest solution to eliminate temporary objects and to speed up your application in run time. It may have some compile time penatly, but the prise is worth :-)