Given the following functions:
1)
IntMatrix operator+(const IntMatrix &matrix, int scalar);
2)
IntMatrix operator+(int scalar, const IntMatrix &matrix);
Which take a scalar and adds it to every member in the Matrix, Should I declare them outside the class (like what is shown above) or inside my class?
In collage they thought as that if we need it to work in both directions (symmetrical behaviour) we declare it out but here it's a little bit complicated...
Function 1 can be written inside the class, as a member function, but function 2 must be written as a non-member function, since the left hand side is not a IntMatrix.
I would suggest writing a operator+= that takes an int as a member function. Then you can easily call that from both operator+, which you can write as non-members.
So your operator+ (as non-members) would look like this:
IntMatrix operator+(IntMatrix matrix, int scalar) {
return matrix += scalar;
}
IntMatrix operator+(int scalar, IntMatrix matrix) {
return matrix += scalar;
}
I am building a template matrix class for use in my future c++ code. I have a few questions regarding value passing for overloaded operators, exceptions vs asserts, and general class design.
Am I passing the values correctly? Is it efficient? What can I do otherwise to make it better?
This library is built with future application design in mind (terminal or gui), where a user could define their own matrices and run calculations. Would using exceptions instead of asserts be better in this case?
I have looked up the rule of 5 for c++, where it states that:
Because the presence of a user-defined destructor, copy- constructor, or copy-assignment operator prevents implicit definition of the move constructor and the move assignment operator, any class for which move semantics are desirable, has to declare all five special member functions.
Can I get away with not implementing this rule by just not having any of those three?** What would be the standard way to make this class more functional?
I have subtraction, multiplication, and division (scalar) defined in my program with the same/similar structure as the provided addition operator definitions, so not all of that code is necessary here.
Any hard advice or criticism on the overall design is accepted!
#ifndef MACMATRICES_H
#define MACMATRICES_H
#include <vector>
#include <iomanip>
#include <iostream>
#include <exception>
#include "../../DMF-Terminal.h"
namespace DMF
{
template <typename T>
class matrix
{
public:
// Constructors
matrix();
matrix(int p_rows, int p_columns);
// Operators
std::vector<T>& operator[] (size_t i) { return m[i]; }
matrix<T> operator+(const matrix<T>& rhs);
matrix<T> operator+(const T& rhs);
matrix<T>& operator+=(const matrix<T>& rhs);
matrix<T>& operator+=(const T& rhs);
// Class Methods
void print() const;
matrix<T> inverse();
T determinant();
// Observers
bool isSquare() const;
int rowSize() const { return m_rows; }
int colSize() const { return m_cols; }
private:
int m_rows, m_cols;
std::vector< std::vector<T> > m;
};
/* Constructors -----------------------------------------------------------------------------------*/
template <typename T>
matrix<T>::matrix(){}
template <typename T>
matrix<T>::matrix(int p_rows, int p_cols) :
m(p_rows, std::vector<T>(p_cols)), m_rows(p_rows), m_cols(p_cols) {}
/* Addition ---------------------------------------------------------------------------------------*/
template <typename T>
matrix<T> matrix<T>::operator+(const matrix<T>& rhs)
{
try
{
if((this->rowSize() == rhs.rowSize()) && (this->colSize() == rhs.colSize()))
{
matrix<T> sum (this->rowSize(), this->colSize());
for(int i = 0; i < this->rowSize() ; ++i)
{
for(int j = 0; j < this->colSize(); ++j)
sum.m[i][j] = this->m[i][j] + rhs.m[i][j];
}
return sum;
}
else throw std::runtime_error("Cannot add matrices, invalid row/column sizes.");
}
catch (std::exception &e)
{
std::cout << "Error: " << e.what(); DMF::wait();
}
}
template <typename T>
matrix<T> matrix<T>::operator+(const T& rhs)
{
matrix<T> sum (this->rowSize(), this->colSize());
for(int i = 0; i < this->rowSize() ; ++i)
{
for(int j = 0; j < this->colSize(); ++j)
sum.m[i][j] = this->m[i][j] + rhs;
}
return sum;
}
template <typename T>
matrix<T>& matrix<T>::operator+=(const matrix<T>& rhs)
{
try
{
if((this->rowSize() == rhs.rowSize()) && (this->colSize() == rhs.colSize()))
{
for(int i = 0; i < this->rowSize() ; ++i)
{
for(int j = 0; j < this->colSize(); ++j)
this->m[i][j] += rhs.m[i][j];
}
return *this;
}
else throw std::runtime_error("Cannot add matrices, invalid row/column sizes.");
}
catch (std::exception &e)
{
std::cout << "Error: " << e.what(); DMF::wait();
}
}
template <typename T>
matrix<T>& matrix<T>::operator+=(const T& rhs)
{
matrix<T> sum (this->rowSize(), this->colSize());
for(int i = 0; i < this->rowSize() ; ++i)
{
for(int j = 0; j < this->colSize(); ++j)
this->m[i][j] += rhs;
}
return *this;
}
}
#endif /* MACMATRICES_H */
As of right now, this code works within a mini terminal program. I also have matrix * matrix and matrix *= matrix operators overloaded and it seems to be working correctly, with the result matrix size being correct.
Am I passing the values correctly? Is it efficient? What can I do otherwise to make it better?
You pass your matrix by (const) reference, so you avoid copy, so it is fine.
You have some "typo" as variable used as matrix<T> sum in operator+=.
You duplicate some information, std::vector knows its size.
linearise std::vector<std::vector<T>> into std::vector<T>> would be more cache friendly, but requires then a proxy class (with another operator[]) to handle operator[], or you might use instead an accessor as operator()(int, int) or operator[](std::pair<int, int>).
This library is built with future application design in mind (terminal or gui), where a user could define their own matrices and run calculations. Would using exceptions instead of asserts be better in this case?
Exceptions are to communicate the error to the user, but currently, you catch it directly to ignore the error with some log... So instead of throwing, you could directly log the error currently.
There are several to fix that issue:
Have matrix size in template argument and use type system to check those error at compilation. require to know size at compilation though.
If you consider that user might be able to ignore/recover from the error, then let's propagate exception. You might probably have dedicated exceptions.
If you consider that user might not be able to ignore/recover from the error, then assert/terminate/UB are possible way.
I have looked up the rule of 5 for c++, where it states that: "Because the presence of a user-defined destructor, copy- constructor, or copy-assignment operator prevents implicit definition of the move constructor and the move assignment operator, any class for which move semantics are desirable, has to declare all five special member functions." Can I get away with not implementing this rule by just not having any of those three? What would be the standard way to make this class more functional?
The rule of 3 has variants:
rule of 5 to also include move constructor and move assignation.
rule of 0, where all member are already RAII friendly and so default implementation is fine.
using std::vector allows to use rule of 0 :-)
So your are fine.
I have a matrix and scalar, lets call the matrix A. if I multiply the scalar to the matrix , when the scalar is on the right(2*A) it multiply all the indexes of the matrix by 2. BUT when I multiply the matrix with scalar on the left(A*2) it doesn't work!.(its should do as 2*A).
This is part of class(with members):
class Mat
{
private:
int **matArray;
int rows;
int cols;
bool validMat;
public:
.../*functions*/
};
this is the function when of the right multiply:
Mat Mat::operator*(int scalarToMultiply){
if(!validMat)
{
Mat resultOperator(0,0);
return (resultOperator);
}
//Mat resultOperator(matToAdd.cols,matToAdd.rows);
Mat resultOperator(cols,rows);
for (int i=0; i<rows; i++){
for (int j=0; j<cols; j++){
resultOperator.matArray[i][j]=matArray[i][j]*scalarToMultiply;
}
}
return (resultOperator);
}
How do I do the other way?
You just need to write the right-hand-side operator:
Mat operator*(int scalar, const Mat& rhs) {
return rhs * scalar;
}
You can define operator* as a free function (after the class):
Mat operator*(int scalarToMultiply, const Mat& mat) { ... }
And if you need access to the private members, make it a friend of your class by adding
friend Mat operator*(int scalarToMultiply, const Mat& mat);
to your class.
If you plan to write operator*, you probably also want to support operator*=. To make your life easier, you can use libraries like Boost.Operators or df.operators. That way you only need to implement the basic operators and the libraries take care of generating the rest for you.
In order to have the int on the left hand side you need to have free function that has two parameters. The you can call the Mat overloaded function inside free function.
Mat operator*(int lhs, Mat rhs)
{
return rhs * lhs;
}
I am doing an addition of matrices using classes.I have declared a class 'Matrix'.now i need to pass an object of Matrix to a function.how do i do that?
Actually, the best way (IMHO) is to overload operator+(). Thus in your code, you'll need to use only +:
class Matrix {
private:
// Your code
public:
// Your code
friend Matrix operator+(const Matrix &c1, const Matrix &c2);
}
friend Matrix operator+(const Matrix &c1, const Matrix &c2) { <--- passing by reference
// Your code to add matrices
}
int main() {
Matrix A, B;
Matrix C = A + B;
}
In the case of the passing by value Matrix sum(Matrix a, Matrix b), you will need to write a copy constructor if memory for matrix is allocated dynamically.
Passing by pointer Matrix sum(Matrix *a, Matrix *b) is a C style coding, so it is still correct, but not preferable for C++.
Matrix object;
// ...
f(object);
You have quite a few ways to do it.
By Value:
void func (Matrix m);
By Reference:
void func (Matrix& m);
Or By Pointer:
void func (Matrix* m);
Which one you use depends on your needs and semantics of the operation.
I'm teaching myself c++ by creating my own data structure class (a matrix, to be exact) and I've changed it to a template class of type <T> from only using doubles. The overloaded matrix operators were pretty standard
// A snippet of code from when this matrix wasn't a template class
// Assignment
Matrix& operator=( const Matrix& other );
// Compound assignment
Matrix& operator+=( const Matrix& other ); // matrix addition
Matrix& operator-=( const Matrix& other ); // matrix subtracton
Matrix& operator&=( const Matrix& other ); // elem by elem product
Matrix& operator*=( const Matrix& other ); // matrix product
// Binary, defined in terms of compound
Matrix& operator+( const Matrix& other ) const; // matrix addition
Matrix& operator-( const Matrix& other ) const; // matrix subtracton
Matrix& operator&( const Matrix& other ) const; // elem by elem product
Matrix& operator*( const Matrix& other ) const; // matrix product
// examples of += and +, others similar
Matrix& Matrix::operator+=( const Matrix& rhs )
{
for( unsigned int i = 0; i < getCols()*getRows(); i++ )
{
this->elements.at(i) += rhs.elements.at(i);
}
return *this;
}
Matrix& Matrix::operator+( const Matrix& rhs ) const
{
return Matrix(*this) += rhs;
}
But now that Matrix can have a type, I'm having trouble determining which of the matrix references should be type <T> and what the consequences would be. Should I allow dissimilar types operate on each other (eg., Matrix<foo> a + Matrix<bar> b is valid)? I'm also a little fuzzy on how
One reason I'm interested in dissimilar types is to facilitate the use of complex numbers in the future. I'm a newbie at c++ but am happy to dive in over my head to learn. If you're familiar with any free online resources that deal with this problem I would find that most helpful.
Edit: no wonder no one thought this made sense all of my angle brackets in the body were treated as tags! I can't figure out how to escape them, so I'll inline code them.
I figure that I should illustrate my comment about parameterizing matrix dimensions, since you might not have seen this technique before.
template<class T, size_t NRows, size_t NCols>
class Matrix
{public:
Matrix() {} // `data` gets its default constructor, which for simple types
// like `float` means uninitialized, just like C.
Matrix(const T& initialValue)
{ // extra braces omitted for brevity.
for(size_t i = 0; i < NRows; ++i)
for(size_t j = 0; j < NCols; ++j)
data[i][j] = initialValue;
}
template<class U>
Matrix(const Matrix<U, NRows, NCols>& original)
{
for(size_t i = 0; i < NRows; ++i)
for(size_t j = 0; j < NCols; ++j)
data[i][j] = T(original.data[i][j]);
}
private:
T data[NRows][NCols];
public:
// Matrix copy -- ONLY valid if dimensions match, else compile error.
template<class U>
const Matrix<T, NRows, NCols>& (const Matrix<U, NRows, NCols>& original)
{
for(size_t i = 0; i < NRows; ++i)
for(size_t j = 0; j < NCols; ++j)
data[i][j] = T(original.data[i][j]);
return *this;
}
// Feel the magic: Matrix multiply only compiles if all dimensions
// are correct.
template<class U, size_t NOutCols>
Matrix<T, NRows, NOutCols> Matrix::operator*(
const Matrix<T, NCols, NOutCols>& rhs ) const
{
Matrix<T, NRows, NOutCols> result;
for(size_t i = 0; i < NRows; ++i)
for(size_t j = 0; j < NOutCols; ++j)
{
T x = data[i][0] * T(original.data[0][j]);
for(size_t k = 1; k < NCols; ++k)
x += data[i][k] * T(original.data[k][j]);
result[i][j] = x;
}
return result;
}
};
So you'd declare a 2x4 matrix of floats, initialized to 1.0, as:
Matrix<float, 2, 4> testArray(1.0);
Note that there is no requirement for the storage to be on the heap (i.e. using operator new) since the size is fixed. You could allocate this on the stack.
You can create another couple matrices of ints:
Matrix<int, 2, 4> testArrayIntA(2);
Matrix<int, 4, 2> testArrayIntB(100);
For copying, dimensions must match though types do not:
Matrix<float, 2, 4> testArray2(testArrayIntA); // works
Matrix<float, 2, 4> testArray3(testArrayIntB); // compile error
// No implementation for mismatched dimensions.
testArray = testArrayIntA; // works
testArray = testArrayIntB; // compile error, same reason
Multiplication must have the right dimensions:
Matrix<float, 2, 2> testArrayMult(testArray * testArrayIntB); // works
Matrix<float, 4, 4> testArrayMult2(testArray * testArrayIntB); // compile error
Matrix<float, 4, 4> testArrayMult2(testArrayIntB * testArray); // works
Note that, if there's a botch, it is caught at compile time. This is only possible if the matrix dimensions are fixed at compile time, though. Also note that this bounds checking results in no additional runtime code. It's the same code that you'd get if you just made the dimensions constant.
Resizing
If you don't know your matrix dimensions at compile time, but must wait until runtime, this code may not be of much use. You'll have to write a class that internally stores the dimensions and a pointer to the actual data, and it will need to do everything at runtime. Hint: write your operator [] to treat the matrix as a reshaped 1xN or Nx1 vector, and use operator () to perform multiple-index accesses. This is because operator [] can only take one parameter, but operator () has no such limit. It's easy to shoot yourself in the foot (force the optimizer to give up, at least) by trying to support a M[x][y] syntax.
That said, if there's some kind of standard matrix resizing that you do to resize one Matrix into another, given that all dimensions are known at compile time, then you could write a function to do the resize. For example, this template function will reshape any Matrix into a column vector:
template<class T, size_t NRows, size_t NCols>
Matrix<T, NRows * NCols, 1> column_vector(const Matrix<T, NRows, NCols>& original)
{ Matrix<T, NRows * NCols, 1> result;
for(size_t i = 0; i < NRows; ++i)
for(size_t j = 0; j < NCols; ++j)
result.data[i * NCols + j][0] = original.data[i][j];
// Or use the following if you want to be sure things are really optimized.
/*for(size_t i = 0; i < NRows * NCols; ++i)
static_cast<T*>(result.data)[i] = static_cast<T*>(original.data)[i];
*/
// (It could be reinterpret_cast instead of static_cast. I haven't tested
// this. Note that the optimizer may be smart enough to generate the same
// code for both versions. Test yours to be sure; if they generate the
// same code, prefer the more legible earlier version.)
return result;
}
... well, I think that's a column vector, anyway. Hope it's obvious how to fix it if not. Anyway, the optimizer will see that you're returning result and remove the extra copy operations, basically constructing the result right where the caller wants to see it.
Compile-Time Dimension Sanity Check
Say we want the compiler to stop if a dimension is 0 (normally resulting in an empty Matrix). There's a trick I've heard called "Compile-Time Assertion" which uses template specialization and is declared as:
template<bool Test> struct compiler_assert;
template<> struct compiler_assert<true> {};
What this does is let you write code such as:
private:
static const compiler_assert<(NRows > 0)> test_row_count;
static const compiler_assert<(NCols > 0)> test_col_count;
The basic idea is that, if the condition is true, the template turns into an empty struct that nobody uses and gets silently discarded. But if it's false, the compiler can't find a definition for struct compiler_assert<false> (just a declaration, which isn't enough) and errors out.
Better is Andrei Alexandrescu's version (from his book), which lets you use the declared name of the assertion object as an impromptu error message:
template<bool> struct CompileTimeChecker
{ CompileTimeChecker(...); };
template<> struct CompileTimeChecker<false> {};
#define STATIC_CHECK(expr, msg) { class ERROR_##msg {}; \
(void)sizeof(CompileTimeChecker<(expr)>(ERROR_##msg())); }
What you fill in for msg has to be a valid identifier (letters, numbers, and underscores only), but that's no big deal. Then we just replace the default constructor with:
Matrix()
{ // `data` gets its default constructor, which for simple types
// like `float` means uninitialized, just like C.
STATIC_CHECK(NRows > 0, NRows_Is_Zero);
STATIC_CHECK(NCols > 0, NCols_Is_Zero);
}
And voila, the compiler stops if we mistakenly set one of the dimensions to 0. For how it works, see page 25 of Andrei's book. Note that in the true case, the generated code gets discarded so long as the test has no side effects, so there's no bloat.
I'm not sure I understand what you're asking.
But I would point out that your operator declarations are incorrect and/or incomplete.
Firstly, the assignment operator should return the same type as its parameter; viz:
const Matrix& operator=(const Matrix& src);
Secondly, binary operators return a new object, so you can't return a reference. All binary operators should be declared thus:
Matrix operator+( const Matrix& other ) const; // matrix addition
Matrix operator-( const Matrix& other ) const; // matrix subtracton
Matrix operator&( const Matrix& other ) const; // elem by elem product
Matrix operator*( const Matrix& other ) const; // matrix product
Actually, it is considered better style to declare and implement binary operators as global friend functions instead:
class Matrix { ... };
inline Matrix operator+(const Matrix& lhs,const Matrix& rhs)
{ return Matrix(lhs)+=rhs; }
Hope this helps.
Now I understand what you're asking.
Presumably your implementation of various operators will in this case consist of operations on the composite types. So really the question of whether Matrix op Matrix is meaningful depends on whether string op int is meaningful (and whether such a thing might be useful). You would also need to determine what the return type might be.
Assuming the return type is the same as the LHS operand, the declarations would look something like:
template <typename T>
class Matrix
{
template <typename U>
Matrix<T>& operator+=(const Matrix<U>& rhs);
};
template <typename T,typename U>
Matrix<T> operator+(const Matrix<T>& lhs,const Matrix<U>& rhs)
{ return Matrix<T>(lhs)+=rhs; }
Matrix<double> x = ...;
Matrix<int> y = ...;
cout << x + y << endl; // prints a Matrix<double>?
OK, that's doable, but the problem gets tricky quickly.
Matrix<double> x = ...
Matrix<complex<float>> y = ...
cout << x + y << endl; // Matrix<complex<double>>?
You will most likely be happiest if you require that your binary operators use like-type operands and force your application builders to explicitly type-cast their values. For the latter case:
cout << ((Matrix<complex<double>>) x) + ((Matrix<complex<double>>) y) << endl;
You can provide a member template constructor (or a type conversion operator) to support the conversions.
template <typename T>
class Matrix {
...
public:
template <typename U>
Matrix(const Matrix<U>& that) {
// initialize this by performing U->T conversions for each element in that
}
...
};
The alternative, having your binary operator template deduce the correct Matrix return type based on the element types of the two operands, requires some moderately complex template meta-programming, probably not what you're looking to get into.
First of all, the copy assignment operator should not have const Matrix& as its return type; your interface is correct.
Grant's suggestion of how binary operators are implemented is the generally accepted way of doing these things.
It's a nice exercise, but one quickly sees why doing linear algebra in C++ is a bad idea to begin with. Operations like A+B and A*B are valid only if the dimensions of the matrices match up.
You don't have to add much at all, because inside a template, the class name itself refers to the current template parameter. So the following are equivalent:
template <typename T> struct Foo
{
Foo<T> bar(const Foo<T> &);
Foo bar2(const Foo *); // same
};
So all your operations just go through without change. What you should add is a constructor that converts one matrix type into another:
temlate <typename T> class Matrix
{
template <typename U> Matrix(const Matrix<U> &); // construct from another matrix
/*...*/
};
Using that conversion constructor, you can mix matrices in your operators, as Matrix<T>::operator+(Matrix<U>) will use the conversion to create an argument of type Matrix<T>, and then you use your already implemented operator.
In C++11 you can add static_assert(std::is_convertible<U, T>::value, "Boo"); to your converting constructor to give you a useful compile-time diagnostic if you call it with an incompatible type.