Home > OS >  Scalar multiplication of template class not working
Scalar multiplication of template class not working

Time:06-13

This error is occurring when I am doing scalar multiplication. I am using template classes to perform these operations on matrices. I have been trying to grasp at the concepts, but I seem to be failing. Any help is appreciated.

main.cpp inside main function

    Matrix<int, 3, 3> m4;
    Matrix<int, 3, 3> m5(3);
    m5 = m4 * 2;  //This works
    m5 = 2 * m4;  //Gives an error for this
    cout << m5 << endl;

matrix.h

#include <exception>

template <class T, int M, int N>
Matrix<T, M, N> operator*(T, const Matrix<T, M, N> &);

template <class T, int M, int N>
class Matrix
{
private:
    T mat[M][N];
    int rows = M;
    int cols = N;

public:
    // Error class
    class IllegalOperation : public std::exception
    {
    public:
        IllegalOperation(const char *msg) : _msg(msg) {}
        virtual const char *what() const throw() { return _msg.c_str(); };

    private:
        std::string _msg;
    };
    // constructor
    Matrix(int v = 0)
    {
        for (int i = 0; i < M; i  )
        {
            for (int j = 0; j < N; j  )
                mat[i][j] = v;
        }
    }

    // () overloading
    T &operator()(int i, int j)
    {
        return mat[i][j];
    }

    const T &operator()(int i, int j) const
    {
        return mat[i][j];
    }

    // [] overloading
    T *operator[](int index)
    {
        return mat[index];
    }
    const T *operator[](int index) const
    {
        return mat[index];
    }

    // << overloading
    friend std::ostream &operator<<(std::ostream &os, const Matrix<T, M, N> &L)
    {
        for (int i = 0; i < M; i  )
        {
            for (int j = 0; j < N; j  )
                os << L.mat[i][j] << " ";
            os << "\n";
        }
        return os;
    }

    template <class T1, int M1, int N1>
    Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other);
    template <class T1, int M1, int N1>
    const Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other) const;
    Matrix<T, M, N> operator (Matrix<T, M, N> const &other);

    // scalar
    Matrix<T, M, N> operator*(T);
    friend Matrix<T, M, N> operator*<>(T scalar, const Matrix<T, M, N> &other);

    friend T min(Matrix obj)
    {
        T result = obj.mat[0][0];
        for (int i = 0; i < M; i  )
        {
            for (int j = 0; j < N; j  )
                if (result < obj.mat[i][j])
                    result = obj.mat[i][j];
        }
        return result;
    }

    long double avg() const
    {
        long double result = 0;
        for (int i = 0; i < M; i  )
        {
            for (int j = 0; j < N; j  )
                if (result < mat[i][j])
                    result = result   mat[i][j];
        }
        return result / (M * N);
    }
};

template <class T, int M, int N>
Matrix<T, M, N> Matrix<T, M, N>::operator (Matrix const &other)
{
    if ((this->rows == other.rows) && (this->cols == other.cols))
    {
        Matrix<T, M, N> resultantMatrix;

        for (auto i = 0; i < this->rows; i  )
        {
            for (auto j = 0; j < this->cols; j  )
            {
                auto &valueFirst = this->mat[i][j];
                auto &valueSecond = other.mat[i][j];

                // if ((additionOverflow(valueFirst, valueSecond)) || (additionUnderflow(valueFirst, valueSecond)))
                //     throw std::out_of_range("Resultant value of matrix is out of range");
                // else
                resultantMatrix(i, j) = valueFirst   valueSecond;
            }
        }
        return resultantMatrix;
    }
    else
        throw IllegalOperation("Matrices cannot be added, sizes do not match");
}

template <class T, int M, int N>
template <class T1, int M1, int N1>
Matrix<T, M, N1> Matrix<T, M, N>::operator*(Matrix<T1, M1, N1> const &other)
{
    std::cout << M << " " << N1;
    if (N == M1)
    {
        Matrix<T, M, N1> resultantMatrix;

        for (auto i = 0; i < this->rows; i  )
        {
            for (auto j = 0; j < this->cols; j  )
            {
                for (auto k = 0; k < this->cols; k  )
                {
                    auto &valueFirst = this->mat[i][k];
                    auto &valueSecond = other(k, j);

                    // if ((additionOverflow(valueFirst, valueSecond)) || (additionUnderflow(valueFirst, valueSecond)))
                    //     throw std::out_of_range("Resultant value of matrix is out of range");
                    // else
                    resultantMatrix(i, j)  = valueFirst * valueSecond;
                }
            }
        }
        return resultantMatrix;
    }
    else
        throw IllegalOperation("Matrices cannot be multipled, sizes not compatible");
}

template <class T, int M, int N>
template <class T1, int M1, int N1>
Matrix<T, M, N1> const Matrix<T, M, N>::operator*(Matrix<T1, M1, N1> const &other) const
{
    if (N == M1)
    {
        Matrix<T, M, N1> resultantMatrix;

        for (auto i = 0; i < this->rows; i  )
        {
            for (auto j = 0; j < this->cols; j  )
            {
                for (auto k = 0; k < this->cols; k  )
                {
                    auto &valueFirst = this->mat[i][k];
                    auto &valueSecond = other(k, j);

                    // if ((additionOverflow(valueFirst, valueSecond)) || (additionUnderflow(valueFirst, valueSecond)))
                    //     throw std::out_of_range("Resultant value of matrix is out of range");
                    // else
                    resultantMatrix(i, j)  = valueFirst * valueSecond;
                }
            }
        }
        return resultantMatrix;
    }
    else
        throw IllegalOperation("Matrices cannot be multipled, sizes not compatible");
}

Function for m * 2, and this works

// scalar m * T
template <class T, int M, int N>
Matrix<T, M, N> Matrix<T, M, N>::operator*(T scalar)
{
    Matrix<T, M, N> resultantMatrix;

    for (auto i = 0; i < this->rows; i  )
    {
        for (auto j = 0; j < this->cols; j  )
        {
            auto valueFirst = this->mat[i][j];
            if (scalar == 0)
                resultantMatrix(i, j) = 0;
            // else if ((multiplicationOverflow(valueFirst, scalar)) || (multiplicationUnderflow(valueFirst, scalar)))
            //     throw std::out_of_range("Resultant value of matrix is out of range");
            else
                resultantMatrix(i, j) = this->mat[i][j] * scalar;
        }
    }
    return resultantMatrix;
}

Function for 2 * m, this does not work

template <class T, int M, int N>
Matrix<T, M, N> operator*(T scalar, const Matrix<T, M, N> &other)
{
    Matrix<T, M, N> resultantMatrix;

    for (auto i = 0; i < M; i  )
    {
        for (auto j = 0; j < N; j  )
        {
            auto valueFirst = other(i, j);
            if (scalar == 0)
                resultantMatrix(i, j) = 0;
            // else if ((multiplicationOverflow(valueFirst, scalar)) || (multiplicationUnderflow(valueFirst, scalar)))
            //     throw std::out_of_range("Resultant value of matrix is out of range");
            else
                resultantMatrix(i, j) = other(i, j) * scalar;
        }
    }
    return resultantMatrix;
}

Errors

In file included from main.cpp:3:
matrix.h:4:1: error: ‘Matrix’ does not name a type
    4 | Matrix<T, M, N> operator*(T, const Matrix<T, M, N> &);
      | ^~~~~~
matrix.h: In instantiation of ‘class Matrix<int, 3, 2>’:
main.cpp:10:29:   required from here
matrix.h:76:28: error: template-id ‘operator*<>’ for ‘Matrix<int, 3, 2> operator*(int, const Matrix<int, 3, 2>&)’ does not match any template declaration
   76 |     friend Matrix<T, M, N> operator*<>(T scalar, const Matrix<T, M, N> &other);
      |                            ^~~~~~~~~~~
matrix.h:210:17: note: candidates are: ‘Matrix<T, M, N> Matrix<T, M, N>::operator*(T)’
  210 | Matrix<T, M, N> Matrix<T, M, N>::operator*(T scalar)
      |                 ^~~~~~~~~~~~~~~
matrix.h:71:28: note:                 ‘template<class T, int M, int N> template<class T1, int M1, int N1> const Matrix<T, M, N1> Matrix<T, M, N>::operator*(const Matrix<T1, M1, N1>&) const’
   71 |     const Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other) const;
      |                            ^~~~~~~~
matrix.h:69:22: note:                 ‘template<class T, int M, int N> template<class T1, int M1, int N1> Matrix<T, M, N1> Matrix<T, M, N>::operator*(const Matrix<T1, M1, N1>&)’
   69 |     Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other);
      |                      ^~~~~~~~
matrix.h: In instantiation of ‘class Matrix<int, 3, 3>’:
main.cpp:12:25:   required from here
matrix.h:76:28: error: template-id ‘operator*<>’ for ‘Matrix<int, 3, 3> operator*(int, const Matrix<int, 3, 3>&)’ does not match any template declaration
   76 |     friend Matrix<T, M, N> operator*<>(T scalar, const Matrix<T, M, N> &other);
      |                            ^~~~~~~~~~~
matrix.h:210:17: note: candidates are: ‘Matrix<T, M, N> Matrix<T, M, N>::operator*(T)’
  210 | Matrix<T, M, N> Matrix<T, M, N>::operator*(T scalar)
      |                 ^~~~~~~~~~~~~~~
matrix.h:71:28: note:                 ‘template<class T, int M, int N> template<class T1, int M1, int N1> const Matrix<T, M, N1> Matrix<T, M, N>::operator*(const Matrix<T1, M1, N1>&) const’
   71 |     const Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other) const;
      |                            ^~~~~~~~
matrix.h:69:22: note:                 ‘template<class T, int M, int N> template<class T1, int M1, int N1> Matrix<T, M, N1> Matrix<T, M, N>::operator*(const Matrix<T1, M1, N1>&)’
   69 |     Matrix<T, M, N1> operator*(Matrix<T1, M1, N1> const &other);

CodePudding user response:

You need to forward declare your class before you use it, like this.

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> &); 

template <class T, int M, int N>
class Matrix
{
    ...
};

A simpler option would be to remove the declaration of operator* and just define it after the definition of Matrix. Like this

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> &)
{
    ...
}

but maybe that will cause problems elsewhere in your code, I can't see enough of it to tell.

  •  Tags:  
  • c
  • Related