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.