I'm learning C++, so please be patient with me.
This is my matrix class
template<class T = double> class Matrix {
using sequence_type = std::vector<T>;
public:
... some methods and constructors
Matrix_ref<T> col(Index i_) { if (i_ < 0 || i_ > r) _error("out_of_bound"); return Matrix_ref<T>(elems.data(), Matrix_slice(i_, r, c), r); }
Matrix_ref<T> row(Index i_) { if (i_ < 0 || i_ > c) _error("out_of_bound"); return Matrix_ref<T>(elems.data(), Matrix_slice(i_ * c, c, 1), c); }
const Matrix_ref<T> col(Index i_) const { if (i_ < 0 || i_ > r) _error("out_of_bound"); return Matrix_ref<T>(elems.data(), Matrix_slice(i_, r, c), r); }
const Matrix_ref<T> row(Index i_) const { if (i_ < 0 || i_ > c) _error("out_of_bound"); return Matrix_ref<T>(elems.data(), Matrix_slice(i_ * c, c, 1), c); }
Matrix_ref<T> operator[](Index r_) { return row(r_); }
private:
sequence_type elems;
Index r;
Index c;
...other methods
};
This is a struct that return correct index of an element in a row (practically it calculate the "stride")
struct Matrix_slice {
Matrix_slice(Index first_, Index size_, Index stride_) : first(first_), size(size_), stride(stride_) {}
const Index first;
const Index size;
const Index stride;
Index operator()(Index i) { return first + stride * i; }
const Index operator()(Index i) const { return first + stride * i; }
};
And this is a "reference" to the matrix. If I use the [] operator with the matrix, I get a matrix_ref.
template<class T = double> class Matrix_ref {
public:
Matrix_ref(T* elems_, Matrix_slice slice_, Index ref_size_) : elems(elems_), slice(slice_), ref_size(ref_size_) {}
T& at(Index i) { if (i < 0 || i >= ref_size) _error("out_of_bound"); return elems[slice(i)]; }
const T& at(Index i) const { if (i < 0 || i >= ref_size) _error("out_of_bound"); return elems[slice(i)]; }
T& operator[](Index i) { return elems[slice(i)]; }
const T operator[](Index i) const { return elems[slice(i)]; }
constexpr Index size() const { return ref_size; }
private:
T* elems;
const Matrix_slice slice;
const Index ref_size;
};
This is the definition of operator*:
template<class T> Matrix<T> operator*(const Matrix<T>& a, const Matrix<T>& b) {
if (a.cols() != b.rows()) _error("Matrix size mismatch");
Matrix<T> res(a.rows(), b.cols());
for (Index i = 0; i < res.rows(); ++i)
for (Index j = 0; j < res.cols(); ++j)
res.at(i, j) = a.row(i) * b.col(j);
return res;
}
The problem is here -> operator*(const Matrix& a, const Matrix& b) If I declare this operator with const Matrix& a and const...b, it doesn't works, but if I declare without const keyword, It works. But I think it's better to use const. How can I fix it? I think the problem is the fact that Matrix_ref has not T* elems declared as const. If I declare it as const, it works, but I can't modify a Matrix. I got the error at the return of the row/col method in Matrix class caused by this line "res.at(i, j) = a.row(i) * b.col(j);" in overload operator* function.
Complete code: https://github.com/H0lm3s/Matrix/tree/master