I have to make a school project, which work with matrices. In Visual Studio 2010 everything works fine. The tester server have the "matrix_base" and the main function, for example:
template<class T, int N, int M, class LeftOp, class RightOp> class my_matrixAdd;
template<class T, int N, int M, class LeftOp, class RightOp> class my_matrixSub;
template<class T, int N, int M, class LeftOp, class RightOp> class my_matrixMul;
template<class T, int N, int M>
class my_matrix //: matrix_base
{
private:
T arrData[N][M];
int columns;
int rows;
public:
my_matrix() : columns(N), rows(M) {}
template<class LeftOp, class RightOp>
my_matrix<T, N, M> & operator=(
const my_matrixAdd<T, N, M, LeftOp, RightOp> & mx)
{
for(int i=0; i<N; ++i)
for(int j=0; j<M; ++j)
{
At(i, j) = mx.At(i, j);
}
return *this;
}
template<class LeftOp, class RightOp>
my_matrix<T, N, M> & operator=(
const my_matrixMul<T, N, M, LeftOp, RightOp> & mx)
{
for(int i=0; i<N; ++i)
for(int j=0; j<M; ++j)
{
At(i, j) = mx.At(i, j);
}
return *this;
}
template<class LeftOp, class RightOp>
my_matrix<T, N, M> & operator=(
const my_matrixSub<T, N, M, LeftOp, RightOp> & mx)
{
for(int i=0; i<N; ++i)
for(int j=0; j<M; ++j)
{
At(i, j) = mx.At(i, j);
}
return *this;
}
virtual ~my_matrix() {}
const T& At(int n, int m) const
{
return arrData[n][m];
}
T& At(int n, int m)
{
return arrData[n][m];
}
const T& operator()(int n, int m) const
{
return arrData[n][m];
};
T& operator()(int n, int m)
{
return arrData[n][m];
};
int Columns() const { return columns; }
int Rows() const { return rows; }
};
template< class T, int N, int M, class LeftOp, class RightOp>
class my_matrixAdd
{
private:
const LeftOp& m_lhs;
const RightOp& m_rhs;
public:
my_matrixAdd(
const LeftOp& lhs, const RightOp& rhs) :
m_lhs(lhs), m_rhs(rhs) {}
T At(int x, int y) const
{
return m_lhs.At(x, y) + m_rhs.At(x, y);
}
};
template<class T, int N, int M>
inline my_matrixAdd<T, N, M, my_matrix<T, N, M> , my_matrix<T, N, M> >
operator+(const my_matrix<T, N, M> &l, const my_matrix<T, N, M> &r)
{
return my_matrixAdd<T, N, M, my_matrix<T, N, M> ,
my_matrix<T, N, M> > (l, r);
}
template<class T, int N, int M, class LeftOp, class RightOp>
inline my_matrixAdd<T, N, M, my_matrixAdd<T, N, M, LeftOp, RightOp> ,
my_matrix<T, N, M> >
operator+(const my_matrixAdd<T, N, M, LeftOp, RightOp> &l,
const my_matrix<T, N, M> &r)
{
return my_matrixAdd<T, N, M, my_matrixAdd<T, N, M, LeftOp, RightOp> ,
my_matrix<T, N, M> > (l, r);
}
template<class T, int N, int M, class LeftOp, class RightOp>
inline my_matrixAdd<T, N, M, my_matrixSub<T, N, M, LeftOp, RightOp> ,
my_matrix<T, N, M> >
operator+(const my_matrixSub<T, N, M, LeftOp, RightOp> &l,
const my_matrix<T, N, M> &r)
{
return my_matrixAdd<T, N, M, my_matrixSub<T, N, M, LeftOp, RightOp> ,
my_matrix<T, N, M> > (l, r);
}
int main()
{
my_matrix<int,2,2> mtx1;
my_matrix<int,2,2> mtx2;
my_matrix<int,2,2> mtx3;
my_matrix<int,2,2> mtx4;
mtx4 = mtx1 + mtx2 + mtx3;
return 0;
}
The compiler in the server is a g++ with -static -O2 parameters.
And i get errors like:
/var/www/F/I704e/3/1/teszt1.cpp: In function ‘int main()’:
/var/www/F/I704e/3/1/teszt1.cpp:42: error: no match for ‘operator+’ in ‘operator+(const my_matrix&, const my_matrixAdd&) [with T = int, int N = 5, int M = 3, LeftOp = my_matrix, RightOp = my_matrix](((const my_matrixAdd, my_matrix >&)((const my_matrixAdd, my_matrix >*)(& operator+(const my_matrix&, const my_matrix&) [with T = int, int N = 5, int M = 3](((const my_matrix&)((const my_matrix*)(& mtx3)))))))) + operator+(const my_matrixAdd&, const my_matrix&) [with T = int, int N = 5, int M = 3, LeftOp = my_matrix, RightOp = my_matrix](((const my_matrix&)((const my_matrix*)(& mtx6))))’
And like:
In file included from /var/www/F/I704e/3/1/teszt1.cpp:6:
/var/www/Hallg/I704e/3/h145172/7/feladat.cpp: In function ‘my_matrixAdd, my_matrixAdd > operator+(const my_matrixAdd&, const my_matrixAdd&) [with T = int, int N = 5, int M = 3, LeftOp = my_matrix, RightOp = my_matrix]’:
Please help me! Thank You!
This is an extended comment.
Here is my stripping of all of the unrequired stuff in your question:
template<class LeftOp, class RightOp>
class my_matrixAdd;
struct matrix_base {};
class my_matrix : matrix_base
{
public:
my_matrix() {}
template<class LeftOp, class RightOp>
my_matrix & operator=(const my_matrixAdd<LeftOp, RightOp> & mx) {
return *this;
}
virtual ~my_matrix() {}
};
template< class LeftOp, class RightOp>
class my_matrixAdd
{
private:
const LeftOp& m_lhs;
const RightOp& m_rhs;
public:
my_matrixAdd(const LeftOp& lhs, const RightOp& rhs) : m_lhs(lhs), m_rhs(rhs) {}
};
inline my_matrixAdd<my_matrix , my_matrix >
operator+(const my_matrix &l, const my_matrix &r) {
return my_matrixAdd<my_matrix, my_matrix > (l, r);
}
template<class LeftOp, class RightOp>
inline my_matrixAdd<my_matrixAdd<LeftOp, RightOp> , my_matrix >
operator+(const my_matrixAdd<LeftOp, RightOp> &l, const my_matrix &r) {
return my_matrixAdd<my_matrixAdd<LeftOp, RightOp>, my_matrix>(l, r);
}
#include <utility>
int main() {
my_matrix mtx1;
my_matrix mtx2;
my_matrix mtx3;
my_matrix mtx4;
// really, we should figure out what type these are explicitly, instead of using auto:
auto&& tmp1 = mtx1 + mtx2;
auto&& tmp2 = std::move(tmp1) + mtx3;
mtx4 = std::move(tmp2);
auto&& tmp3 = mtx2 + mtx3;
auto&& tmp4 = mtx1 + std::move(tmp3);
mtx4 = std::move(tmp4);
return 0;
}
note that this version also fails to compile. The reason is more obvious, however.
You should strip your code down to something like this, either ask for help understanding why there is still an error, fix it (or note that there is no longer a problem), then build it back up one step at a time.
You'll note that the classes don't do anything anymore -- which is good, because a type error isn't caused by what distant code does. (at worst, it is caused by their signature, which I left unchanged).
Related
I am writing a matrix library for generic types using expression templates.
The basic matrix class is a template class Matrix <typename Scalar, int RowSize, int ColumnSize>
which inherits from MatrixXpr< Matrix<Scalar, RowSize, ColumnSize> >
where MatrixXpr is the parent class for the expression templates "MatrixSum", "MatrixProduct" etc.
For example:
template <typename Mat, typename Rix>
class MatrixProduct : public MatrixXpr< MatrixProduct<Mat,Rix> >
{
private:
const Mat& A_;
const Rix& B_;
public:
using value_type= std::common_type_t<typename Mat::value_type, typename Rix::value_type>;
MatrixProduct(const Mat& A, const Rix& B) : A_(A), B_(B) {}
value_type operator()(int i, int j) const {
value_type out{ 0 };
for (int k = 0; k < A_.Columns(); ++k) out += A_(i, k) * B_(k, j);
return out;
}
};
The * operator is then defined outside
template <typename Mat, typename Rix>
MatrixProduct<Mat, Rix> inline const operator*(const MatrixXpr<Mat>& A, const MatrixXpr<Rix>& B)
{
return MatrixProduct<Mat, Rix>(A, B);
}
Now I wish to implement also a Scalar*Matrix class. But I fail to define the correct value_type:
template <typename Scalar, typename Mat>
class ScalarMatrixProduct : public MatrixXpr< ScalarMatrixProduct<Scalar, Mat> >
{
private:
const Scalar& A_;
const Mat& B_;
public:
using value_type = std::common_type_t<typename Mat::value_type, typename Scalar>;
ScalarMatrixProduct(const Scalar& A, const Mat& B) : A_(A), B_(B) {}
value_type operator()(int i, int j) const {
return A_ * B_(i, j);
}
};
template <typename Scalar, typename Mat>
typename std::enable_if < (!is_matrix<Scalar>::value),
ScalarMatrixProduct<Scalar, Mat > >::type const operator*(const Scalar& A, const MatrixXpr<Mat>& B)
{
return ScalarMatrixProduct<Scalar, Mat>(A, B);
}
On Mac and Linux I get an compilation error of this sort:
template argument 2 is invalid 102 | using value_type =
std::common_type_t<typename Mat::value_type, typename Scalar>;
Interestingly, it compiles on Windows.
Any hints for what's wrong would be helpful.
Thanks in advance.
Complete example:
#include <type_traits>
#include <iostream>
#include <array>
#include <initializer_list>
///////////Expression Template Base Class for CRTP
template <class MatrixClass> struct MatrixXpr {
decltype(auto) operator()(int i, int j) const {
return static_cast<MatrixClass const&>(*this)(i, j);
}
operator MatrixClass& () {
return static_cast<MatrixClass&>(*this);
}
operator const MatrixClass& () const {
return static_cast<const MatrixClass&>(*this);
}
int Rows()
{
return static_cast<MatrixClass&>(*this).Rows();
}
int Columns()
{
return static_cast<MatrixClass&>(*this).Columns();
}
int Rows() const
{
return static_cast<const MatrixClass&>(*this).Rows();
}
int Columns() const
{
return static_cast<const MatrixClass&>(*this).Columns();
}
friend int Rows(const MatrixXpr& A)
{
return A.Rows();
}
friend int Columns(const MatrixXpr& A)
{
return A.Columns();
}
};
template <typename MatrixClass>
std::ostream& operator<<(std::ostream& os, const MatrixXpr<MatrixClass>& A)
{
for (int r = 0; r < Rows(A); ++r) {
os << '[';
for (int c = 0; c < Columns(A); ++c)
os << A(r, c) << (c + 1 < Columns(A) ? " " : "");
os << "]\n";
}
return os;
}
/////////// Matrix Product
template <typename Mat, typename Rix>
class MatrixProduct : public MatrixXpr< MatrixProduct<Mat, Rix> >
{
private:
const Mat& A_;
const Rix& B_;
public:
using value_type = std::common_type_t<typename Mat::value_type, typename Rix::value_type>;
MatrixProduct(const Mat& A, const Rix& B) : A_(A), B_(B)
{
std::cout << "MatrixMatrixProduct Constructor\n";
}
int Rows() const { return A_.Rows(); }
int Columns() const { return B_.Columns(); }
value_type operator()(int i, int j) const {
value_type out{ 0 };
for (int k = 0; k < A_.Columns(); ++k) out += A_(i, k) * B_(k, j);
return out;
}
};
/////////// Scalar Matrix Product
template <typename Scalar, typename Mat>
class ScalarMatrixProduct : public MatrixXpr< ScalarMatrixProduct<Scalar, Mat> >
{
private:
const Scalar& A_;
const Mat& B_;
public:
using value_type = std::common_type_t<typename Mat::value_type, typename Scalar>;
ScalarMatrixProduct(const Scalar& A, const Mat& B) : A_(A), B_(B) {
std::cout << "ScalarMatrixProduct Constructor\n";
}
int Rows() const { return B_.Rows(); }
int Columns() const { return B_.Columns(); }
value_type operator()(int i, int j) const {
return A_ * B_(i, j);
}
};
//The following two functions are Helpers for initializing an array.
//Source: https://stackoverflow.com/a/38934685/6176345
template<typename T, std::size_t N, std::size_t ...Ns>
std::array<T, N> make_array_impl(
std::initializer_list<T> list,
std::index_sequence<Ns...>)
{
return std::array<T, N>{ *(list.begin() + Ns) ... };
}
template<typename T, std::size_t N>
std::array<T, N> make_array(std::initializer_list<T> list) {
if (N > list.size())
throw std::out_of_range("Initializer list too small.");
return make_array_impl<T, N>(list, std::make_index_sequence<N>());
}
/////////// Matrix class
template <typename Scalar, int RowSize, int ColumnSize = RowSize>
class Matrix : public MatrixXpr< Matrix<Scalar, RowSize, ColumnSize> >
{
std::array<Scalar, RowSize* ColumnSize> data_;
public:
using value_type = Scalar;
const static int rows_ = RowSize;
const static int columns_ = ColumnSize;
int Rows() const { return rows_; }
int Columns() const { return columns_; }
Matrix() : data_{ Scalar(0) } {};
Matrix(const Matrix& other) = default;
Matrix(Matrix&& other) = default;
Matrix& operator=(const Matrix& other) = default;
Matrix& operator=(Matrix&& other) = default;
~Matrix() = default;
Matrix(std::initializer_list<Scalar> data) : data_(make_array<Scalar, RowSize* ColumnSize>(data)) {}
template <typename Source>
Matrix& operator=(const MatrixXpr<Source>& source)
{
for (int i = 0; i < rows_; ++i)
for (int j = 0; j < columns_; ++j)
data_[MatrixIndex(i, j)] = source(i, j);
return *this;
}
template <typename Source>
Matrix(const MatrixXpr<Source>& source)
{
for (int i = 0; i < rows_; ++i)
for (int j = 0; j < columns_; ++j)
data_[MatrixIndex(i, j)] = source(i, j);
}
Scalar& operator()(int i, int j) {
return data_[MatrixIndex(i, j)];
}
const Scalar& operator()(int i, int j) const {
return data_[MatrixIndex(i, j)];
}
private:
inline static int MatrixIndex(int i, int j)
{
return i * columns_ + j;
}
};
/////////// Multiplication operators
template <typename Mat, typename Rix>
MatrixProduct<Mat, Rix> inline const operator*(const MatrixXpr<Mat>& A, const MatrixXpr<Rix>& B)
{
std::cout << "Matrix Matrix Multiplication\n";
return MatrixProduct<Mat, Rix>(A, B);
}
template <typename Scalar, typename Mat>
typename std::enable_if_t<!std::is_base_of_v<MatrixXpr<Scalar>, Scalar>,
ScalarMatrixProduct<Scalar, Mat >> const operator*(const Scalar& A, const MatrixXpr<Mat>& B)
{
return ScalarMatrixProduct<Scalar, Mat>(A, B);
}
/////////// Failing example
int main()
{
Matrix<int, 2, 2> m = { 1,0,0,1 };
auto n = 3 * m;
std::cout << n;
std::cout << m * n;
//std::cout << n * m; // Error
return 0;
}
Edit:
The above code originally had two problems.
The first one is that my type checking failed to see which overload of the *operator was being used. The above implementation with std::is_base_of_v<MatrixXpr<Scalar>, Scalar> fixed it and is is working correctly.
I do not know why this old code did not work. Here is the old version:
template <typename T>
struct is_matrix : std::false_type {};
template <typename T>
struct is_matrix<const T> : is_matrix<T> {};
template <typename MatrixClass>
struct is_matrix<MatrixXpr<MatrixClass> > : std::true_type {};
template <typename Scalar, typename Mat>
typename std::enable_if < (!is_matrix<Scalar>::value),
ScalarMatrixProduct<Scalar, Mat > >::type const operator*(const Scalar& A, const MatrixXpr<Mat>& B)
{
std::cout << "Scalar Matrix Multiplication\n";
return ScalarMatrixProduct<Scalar, Mat>(A, B);
}
I have problem with implicit conversions in C++.
I'm trying to create some Expression template for vector arithmetics (I know that same libraries already exists. I'm just learning C++ so I wanted to try something with templates).
I would like to create class Vector, that is able to compute like this:
simd::test::Vector<char, 5> a;
simd::test::Vector<short, 5> b;
auto ret = a + b + a + b;
, where on output would be Vector of shorts becouse short is bigger type than char.
Right now, I have class that is able to adds vectors of same data types. For different types I have to call explicit conversion:
//simd::test::Vector<short, 5>(a)
auto ret = simd::test::Vector<short, 5>(a) + b + simd::test::Vector<short, 5>(a) + b;
Is possible to implicit convert Vector before pass into function "operator+()"? Here is my code of Vector:
#pragma once
#include <type_traits>
namespace simd {
namespace test {
template<typename R, std::size_t Dim,
typename std::enable_if<std::is_arithmetic<R>::value>::type* = nullptr
>
class Vector_expression {
public:
static constexpr std::size_t size = Dim;
virtual const R operator[] (std::size_t index) const = 0;
virtual ~Vector_expression() = default;
};
template<typename T, std::size_t Dim>
class Vector final : public Vector_expression<T, Dim> {
private:
T data[Dim];
public:
Vector() = default;
template<typename R>
Vector(const Vector_expression<R, Dim> &obj) {
for(std::size_t index = 0; index < Dim; ++index) {
data[index] = obj[index];
}
}
template<typename R>
Vector(Vector_expression<R, Dim> &&obj) {
for(std::size_t index = 0; index < Dim; ++index) {
data[index] = obj[index];
}
}
template<typename R>
Vector<T, Dim> & operator=(const Vector_expression<R, Dim> &obj) {
for(std::size_t index = 0; index < Dim; ++index) {
data[index] = obj[index];
}
return (*this);
}
template<typename R>
Vector<T, Dim> & operator=(Vector_expression<R, Dim> && obj) {
for(std::size_t index = 0; index < Dim; ++index) {
data[index] = obj[index];
}
return (*this);
}
virtual const T operator[] (std::size_t index) const override {
return data[index];
}
T & operator[] (std::size_t index) {
return data[index];
}
virtual ~Vector() = default;
};
template<typename E1, typename E2, typename R, std::size_t Dim>
class Vector_sum final : public Vector_expression<R, Dim> {
private:
const E1 & _lhs;
const E2 & _rhs;
public:
Vector_sum() = delete;
Vector_sum(const E1 & lhs, const E2 & rhs) :
_lhs(lhs),
_rhs(rhs)
{}
virtual const R operator[] (std::size_t index) const override {
return _lhs[index] + _rhs[index];
}
virtual ~Vector_sum() = default;
};
template<typename R, std::size_t Dim>
Vector_sum<Vector_expression<R, Dim>, Vector_expression<R, Dim>, R, Dim> operator+ (const Vector_expression<R, Dim> & lhs, const Vector_expression<R, Dim> & rhs) {
return {lhs, rhs};
}
}
}
Just define an operator+ that allows different argument types. The one catch is determining the element type of the resulting sum. Probably the best option is to use whatever the result of adding two elements is. One way to write this type is:
decltype(std::declval<const R1>() + std::declval<const R2>())
Or if you know the types are built-in arithmetic types, that would be the same as
std::common_type_t<R1, R2>
Or using a trailing return type, we can take advantage of the function parameters to shorten the std::declval expressions:
template<typename R1, typename R2, std::size_t Dim>
auto operator+ (const Vector_expression<R1, Dim> & lhs,
const Vector_expression<R2, Dim> & rhs)
-> Vector_sum<Vector_expression<R1, Dim>, Vector_expression<R2, Dim>,
decltype(lhs[0] + rhs[0]), Dim>
{
return {lhs, rhs};
}
It could be done using templates and std::common_type, something like this:
template<typename T1, typename T2, size_t S>
simd::test::Vector<typename std::common_type<T1, T2>::type, S>
operator+(simd::test::Vector<T1, S> const& v1,
simd::test::Vector<T2, S> const& v2)
{
// TODO: Implementation...
}
I am trying to play with CRTP with a custom matrix class. Now I am trying to overloading the ostream operator, follow https://msdn.microsoft.com/en-us/library/1z2f6c2k.aspx.
However, everything seems to be compiling but the program never exists and prints nothing on the screen. I am scratching my head as what is happening.
Anyway, this is the relevant code (Sorry it is a bit lengthy)
#ifndef EXPERIMENT_POINTERMATRIX_H
#define EXPERIMENT_POINTERMATRIX_H
#include <cstdlib>
#include <ostream>
#include "macro.h"
namespace PM {
template<typename T, typename Derived>
class MatrixBase{
public:
size_t nRow;
size_t nCol;
MatrixBase(const size_t nRow_,const size_t nCol_):nRow(nRow_), nCol(nCol_){}
Derived& derived(){
return *static_cast<Derived*>(this);
}
const Derived& derived() const{
return *static_cast<Derived*>(this);
}
T& operator()(const size_t i, const size_t j){
CHECK_BOUND(i,j,*this);
return derived().operator()(i,j);
}
const T& operator()(const size_t i, const size_t j) const {
return const_cast<T&>(
static_cast<const MatrixBase<T, Derived>&>(*this).operator()(i,j));
}
inline T rows(){
return nRow;
}
const T rows() const {
return nRow;
}
inline T cols(){
return nCol;
}
const T cols() const {
return nCol;
}
template<typename t1, typename t2>
friend std::ostream& operator<<(std::ostream& os, const MatrixBase<t1, t2> & matrix);
};
template<typename t1, typename t2>
std::ostream& operator<<(std::ostream& os, const MatrixBase<t1, t2>& matrix){
for (size_t i =0;i<matrix.rows();i++){
os << matrix(i,0);
if (matrix.cols()>1) {
for (size_t j = 1; j < matrix.cols(); j++) {
os << "," << matrix(i, j);
}
}
os << std::endl;
}
return os;
};
template<typename T, typename Derived>
class Matrix : public MatrixBase<T, Matrix<T, Derived>>{
public:
T * data;
Matrix(const size_t nRow, const size_t nCol):MatrixBase<T, Matrix<T, Derived>>(nRow, nCol){
data = (T*) malloc(sizeof(T)*nRow*nCol);
}
~Matrix(){
free(data);
}
Derived& derived(){
return *static_cast<Derived*>(this);
}
const Derived& derived() const{
return *static_cast<Derived*>(this);
}
T& operator()(const size_t i, const size_t j){
return derived().operator()(i,j);
}
};
template<typename T, typename Derived>
class MatrixView : public MatrixBase<T, MatrixView<T, Derived>>{
public:
T * data;
MatrixView(const size_t nRow, size_t nCol, T * other):MatrixBase<T, MatrixView<T, Derived>>(nRow, nCol), data(other){}
T& operator()(const size_t i, const size_t j){
return derived().operator()(i,j);
}
Derived& derived(){
return *static_cast<Derived*>(this);
}
const Derived& derived() const{
return *static_cast<Derived*>(this);
}
};
template<typename T>
class MatrixRowMajor: public Matrix<T, MatrixRowMajor<T>>{
public:
MatrixRowMajor(const size_t nRow, const size_t nCol):Matrix<T, MatrixRowMajor<T>>(nRow, nCol){}
T& operator()(const size_t i, const size_t j){
using base = MatrixBase<T, Matrix<T, MatrixRowMajor<T>>>;
using super = Matrix<T, MatrixRowMajor<T>>;
return super::data[i*base::nCol+j];
}
};
template<typename T>
class MatrixColMajor: public Matrix<T, MatrixColMajor<T>>{
public:
MatrixColMajor(const size_t nRow, const size_t nCol):Matrix<T, MatrixColMajor<T>>(nRow, nCol){}
T& operator()(const size_t i, const size_t j){
using base = MatrixBase<T, Matrix<T, MatrixColMajor<T>>>;
using super = Matrix<T, MatrixColMajor<T>>;
return super::data[i+j*base::nRow];
}
};
template<typename T>
class MatrixViewRowMajor : public MatrixView<T, MatrixViewRowMajor<T>>{
public:
MatrixViewRowMajor(const size_t nRow, const size_t nCol, T* other):MatrixView<T, MatrixViewRowMajor<T>>(nRow, nCol, other){}
T& operator()(const size_t i, const size_t j){
using base = MatrixBase<T, Matrix<T, MatrixViewRowMajor<T>>>;
using super = MatrixView<T, MatrixViewRowMajor<T>>;
return super::data[i*base::nCol+j];
}
};
template<typename T>
class MatrixViewColMajor : public MatrixView<T, MatrixViewColMajor<T>>{
public:
MatrixViewColMajor(const size_t nRow, const size_t nCol, T* other):MatrixView<T, MatrixViewRowMajor<T>>(nRow, nCol, other){}
T& operator()(const size_t i, const size_t j){
using base = MatrixBase<T, Matrix<T, MatrixViewRowMajor<T>>>;
using super = MatrixView<T, MatrixViewRowMajor<T>>;
return super::data[i+j*base::nRow];
}
};
}
void test_print(){
using namespace PM;
using namespace std;
MatrixRowMajor<double> matrix(10, 1);
for (int i =0;i<matrix.rows();i++){
matrix(i,0)=1.0;
std::cout << "i'th entry is " <<matrix(i,0) << std::endl; //This is fine
}
std::cout << matrix; //This is not fine
}
#endif //EXPERIMENT_POINTERMATRIX_H
The whole program is compiled using g++4.9 (enabling c++11)
EDIT:
In order to test whether it is the problem of the operator, I create the following methods (at MatrixBase):
void print(){
for (size_t i =0;i<this->rows();i++){
std::cout << this->operator()(i,0);
if (this->cols()>1) {
for (size_t j = 1; j < this->cols(); j++) {
std::cout << "," << this->operator()(i, j);
}
}
std::cout << std::endl;
}
}
and call the methods like matrix.print(). This works as expected.
Unfortunately, the debugger gives no useful information as the program stops in the line os << matrix(i,0), and when I stop the program to retrieve the information, it says fails to get the frame (Clion as debugger)
The (member function of MatrixBase) operator() unconditionally calls itself, so is infinitely recursive.
const T& operator()(const size_t i, const size_t j) const {
return const_cast<T&>(
static_cast<const MatrixBase<T, Derived>&>(*this).operator()(i,j));
}
This function is tail-recursive, so can result in an infinite loop rather than crashing due to great call depths.
Unrelated to your question, it is usually considered inadvisable to use malloc() in C++ - particularly when working with types (e.g. C++ classes) that may not be directly compatible with C - results, for the user of your class, depending on the type T, can be undefined. Use operator new instead. Even better, use a standard container.
When I try to compile the following coding, I have get an error saying
Error 1 error LNK2019: unresolved external symbol "class Matrix __cdecl operator*(int const &,class Matrix &)" (??D#YA?AV?$Matrix#H$02$01##ABHAAV0##Z) referenced in function _main C:\Users\pc\Documents\Visual Studio 2013\Projects\Homework4\Homework4\main.obj Homework4
This error is occurred from the scalar multiplication on matrix and I don't know how to fix it. Can anyone give me an advice on this?
//Matrix.h
#pragma once
#include <iostream>
#include <vector>
using namespace std;
template<class T, int m, int n>
class Matrix
{
vector<vector<T>> elements;
int nrow;
int ncol;
public:
Matrix();
~Matrix();
void print();
vector<T> row(int);
vector<T> col(int);
friend Matrix<T, m, n> operator+<>(const Matrix<T, m, n>&, const Matrix<T, m, n>&);
friend Matrix<T, m, n> operator-<>(const Matrix<T, m, n>&, const Matrix<T, m, n>&);
friend Matrix<T, m, n> operator*(const T&, Matrix<T, m, n>&);
};
template<class T, int m, int n>
Matrix<T, m, n>::Matrix() : nrow(m), ncol(n)
{
for (int i = 0; i < nrow; i++){
vector<T> row(ncol, i);
elements.push_back(row);
}
}
template<class T,int m,int n>
vector<T> Matrix<T, m, n>::row(int i)
{
return elements[i];
}
template<class T, int m, int n>
vector<T> Matrix<T, m, n>::col(int j)
{
vector<T> col;
for (int i = 0; i < ncol; i++)
{
col.push_back(elements[i][j]);
}
return col;
}
template<class T, int m, int n>
Matrix<T, m, n>::~Matrix(){}
template<class T, int m, int n>
void Matrix<T, m, n>::print()
{
for (int i = 0; i < nrow; i++){
for (int j = 0; j < ncol; j++)
{
cout << elements[i][j] << " ";
}
cout << endl;
}
}
template<class T, int m, int n>
Matrix<T, m, n> operator+(const Matrix<T, m, n>& m1, const Matrix<T, m, n>& m2){
Matrix<T, m, n> m3;
int nrow = m1.nrow;
int ncol = m1.ncol;
for (int i = 0; i < nrow; ++i){
for (int j = 0; j < ncol; ++j){
m3.elements[i][j] = m1.elements[i][j] + m2.elements[i][j];
}
}
return m3;
}
template<class T, int m, int n>
Matrix<T, m, n> operator-(const Matrix<T, m, n>& m1, const Matrix<T, m, n>& m2){
Matrix<T, m, n> m3;
int nrow = m1.nrow;
int ncol = m1.ncol;
for (int i = 0; i < nrow; ++i){
for (int j = 0; j < ncol; ++j){
m3.elements[i][j] = m1.elements[i][j] - m2.elements[i][j];
}
}
return m3;
}
template<class T, int m, int n>
Matrix<T, m, n> operator*(const T& c, const Matrix<T, m, n>& m1){
int nrow = m1.nrow;
int ncol = m1.ncol;
Matrix<T, m, n> m2;
for (int i = 0; i < nrow; ++i){
for (int j = 0; j < ncol; ++j){
m2.elements[i][j] = c*m1.elements[i][j];
}
}
return m2;
}
//main.cpp
#include "Matrix.h"
using namespace std;
int main()
{
Matrix<int, 3, 2> a;
Matrix<int, 3, 2> b;
Matrix<int, 3, 2> c;
c = 2*b;
c.print();
}
I think the error comes from the friend function (operation *) in the body of the class, but I don't know how to fix it...
The error occurs because
a) operator* is declared as non-template (you should use <>)
b) if you use <> syntax, you must provide the declaration of the template.
Fix
(Add before Matrix class):
template<class T, int m, int n>
class Matrix;
template<class T, int m, int n>
Matrix<T, m, n> operator*(T&, const Matrix<T, m, n>&);
//class matrix definition here
Add <> to operator* friend declaration:
friend Matrix<T, m, n> operator*<>(T&, const Matrix<T, m, n>&);
I am trying to do Matrix-Matrix multiplication with template and I keep getting following error. ( I am trying to multiply non-square matrix)
Error 1 error C2593: 'operator *' is ambiguous
Can any one give me an advice on how to fix this?
//Matrix.h
#pragma once
#include <iostream>
#include <vector>
using namespace std;
template<class T, int m, int n>
class Matrix;
template<class T, int m, int n, int l>
Matrix<T, m, n> operator*(const Matrix<T, m, n>&, const Matrix<T, n, l>&);
template<class T, int m, int n>
class Matrix
{
vector<vector<T>> elements;
int nrow;
int ncol;
public:
Matrix();
~Matrix();
void print();
template<int l>
friend Matrix<T, m, l> operator*<>(const Matrix<T, m, n>&, const Matrix<T, n, l>&);
};
template<class T, int m, int n>
Matrix<T, m, n>::Matrix() : nrow(m), ncol(n)
{
for (int i = 0; i < nrow; i++){
vector<T> row(ncol, i);
elements.push_back(row);
}
}
template<class T, int m, int n>
Matrix<T, m, n>::~Matrix(){}
template<class T, int m, int n>
void Matrix<T, m, n>::print()
{
for (int i = 0; i < nrow; i++){
for (int j = 0; j < ncol; j++){
cout << elements[i][j] << " ";
}
cout << endl;
}
}
template<class T, int m, int n, int l>
Matrix<T, m, l> operator*(const Matrix<T, m, n>& m1, const Matrix<T, n, l>& m2){
int nrow = m1.nrow;
int ncol = m2.ncol;
Matrix<T, m, l> m3;
for (int i = 0; i < nrow; ++i){
for (int j = 0; j < ncol; ++j){
m3.elements[i][j] = 0;
for (int k = 0; k < m1.ncol; k++){
T temp = m1.elements[i][k] * m2.elements[k][j];
m3.elements[i][j] = temp + m3.elements[i][j];
}
}
}
return m3;
}
//main.cpp
#include "Matrix.h"
using namespace std;
int main()
{
Matrix<int, 3, 2> a;
Matrix<int, 2, 1> b;
Matrix<int, 3, 1> c;
c = a*b;
c.print();
}
The problem occurs in the matrix multiplication possibly due to the coding error in the template.
I had to change what Richard changed, but I also had to change the declaration of operator* and the friend as follows:
template<class T, int m, int n, int l>
Matrix<T, m, l> operator*(const Matrix<T, m, n>&, const Matrix<T, n, l>&);
// ^ here
and:
template<class _T, int _m, int _n, int l>
friend Matrix<_T, _m, l> operator*(const Matrix<_T, _m, _n>&, const Matrix<_T, _n, l>&);
I got the "operator* is ambiguous" error if I didn't change the first of these two, since the forward declaration doesn't match the instantiation further down.
It's currently outputting:
0
1
2
That doesn't seem quite right, but I'm not awake enough to debug further.
The error is here:
./matrix.cpp:48:28: error: function template partial specialization is not allowed
friend Matrix<T, m, l> operator*<>(const Matrix<T, m, n>&, const Matrix<T, n, l>&);
^ ~~
1 error generated.
change it to this:
friend Matrix<T, m, l> operator*(const Matrix<T, m, n>&, const Matrix<T, n, l>&);