Operator = overloading with templates - c++

Seriously, I looked at similar examples, but I still do not get why it is not working. I am having trouble with overloading the = operator.
I get the two following errors:
error C2955: 'Matrix' : use of class template requires template argument list
error C2244: 'Matrix::operator =' : unable to match function definition to an existing declaration
May someone please explain what is wrong?
Thanks to all
//Matrix.hpp
template<typename T>
class Matrix
{
public:
Matrix(int numberRows, int numberColumns);
~Matrix();
void asgValue(T value, int row, int column);
T getValue(int row, int column);
Matrix<T>& operator= (const Matrix<T>& rhs);
friend Matrix<T>& operator+ (const Matrix<T>& lhs, const Matrix<T>& rhs);
private:
T **twoDarray;
int nbrRows;
int nbrColumns;
};
#include "Matrix.inl"
//Matrix.inl
//Matrix<T>& Matrix<T>::operator= (const Matrix<T>& rhs)
template<typename T>
Matrix<T>& Matrix::operator= (const Matrix<T>& rhs)
{
for (int i = 0; i < nbrRows; i++)
{
for (int j = 0; j < nbrColumns; j++)
{
twoDarray[i][j] = rhs.twoDarray[i][j];
}
}
return *this;
}

You need template parameters in the name of the function being defined.
template<typename T>
Matrix<T>& Matrix<T>::operator= (const Matrix<T>& rhs)
// ^ here
You are required to write <T>, although it doesn't add to the expressiveness of the language — the arguments before :: cannot be anything other than the entire class template parameter list in the original order and without any modifications. It is what it is.

Related

Can't multiply two matrices, where hight and width are defined by template

I wrote Class Matrix, parameters of which I define by template. So when I tried to declare operator* between two matrices, I found out? that Cpp counts matrices with different parameters as different classes (For example 7x3 and 3x5). How can I avoid this?
Here is my class
template <size_t N, size_t M, typename T = int64_t>
class Matrix {
public:
Matrix();
Matrix(std::vector<std::vector<T>> const input);
Matrix(const T elem);
Matrix operator+(const Matrix& other) const;
Matrix& operator+=(const Matrix& other);
Matrix operator-(const Matrix& other) const;
Matrix& operator-=(const Matrix& other);
Matrix operator*(const T& other) const;
Matrix& operator*=(const T& other);
Matrix operator*(const Matrix& other) const;
Matrix& operator*=(const Matrix& other);
Matrix Transposed();
T Trace();
T& operator()(const size_t i, const size_t j) const;
bool operator==(const Matrix& other) const;
private:
};
Cppref did not helped :(
Template arguments are part of the type; otherwise they couldn't be considered in type resolution and SFINAE. Thus, there are two choices:
either make N, M runtime arguments of e.g. Matrix (or can even be deduced from current input), thereby making it non-template, or
you live with the fact that the concrete class depends on N, M and, optionally, you might have a base class where this part of the type is erased; or, if you don't need a common base type, you might have the operator as a template and then you might have a different Matrix on the rhs.
The latter can be like this:
typename<T = int64_t>
class Matrix {
Matrix();
Matrix(std::vector<std::vector<T>> const input);
Matrix(const T elem);
// other operators, functions
virtual Matrix operator*(const Matrix& other) const;
};
template <size_t N, size_t M, typename T = int64_t>
class FixedSizeMatrix : Matrix<T> {
// as now, possibly with override when appropriate
Matrix<N, M1> operator*(const Matrix& other) const override /* final? */;
};
However, this will be slower, due to virtual resolution. If you don't need a common base:
template <size_t N, size_t M, typename T = int64_t>
class Matrix {
public:
// as before
template<size_t N1, size_t M1, typename T2 = int64_t>
Matrix operator*(const Matrix<N1, M1, T2>& other) const;
};
Main question to ask yourself is, why you want `N, M` to be compile-time arguments.

How do in include a non-member operator- overloading for a template class in c++?

I am new to c++ and templates is definitely not friendly in syntax. Basically, here are some of the functions i've written, tested, and finished. Just one quick question, i've been trying for hours to write a non-member operator- overload for my matrix class and have been getting all types of syntax errors. So, where do I start?
Here is my myMatrix.h:
#ifndef MYMATRIX_H
#define MYMATRIX_H
#include <exception>
#include <vector>
#include <iostream>
using namespace std;
/* I'm using this matrix to store data */
template<typename T>
using twoD = std::vector<std::vector<T>>;
template<class T>
class Matrix{
private:
int rows;
int cols;
twoD<T> matrix;
protected:
void validSizeCheck(int rows, int cols);
public:
Matrix(int rows, int cols);
Matrix(int rows, int cols, twoD<T> newMatrix);
twoD<T> getMatrix();
int getRows();
int getCols();
void printMatrix();
void operator=(const Matrix<T> &);
Matrix<T> &operator+=(const Matrix<T> &);
Matrix<T> operator+(const Matrix<T> &);
Matrix<T> operator*(const Matrix<T> &);
Matrix<T> operator*(const T &);
};
Here is one of the thing I tried:
template <class T>
Matrix<T> operator-(const Matrix<T>& lhs,const Matrix<T>& rhs){
if(lhs.rows != rhs.cols || lhs.rows != rhs.cols{
throw exception();
}
Matrix tmp(lhs.rows, lhs.cols);
for(int i = 0; i < lhs.rows; i++){
for(int j = 0; j < cols; j++){
tmp.matrix[i][j] = lhs.matrix[i][j]+rhs.matrix[i][j];
}
}
return tmp;
}
Obviously that didn't work..
So what are the syntax that I should be following for this? Also, this might be a very dumb question but should the non-member function be in the header file or the .cpp file? So far, everything that I wrote has been in the .h file as they're all templates..
Any help would be greatly appreciated.
UPDATED:
I finally got the code to works, for class & function declaration, I added this:
template<class T>
class Matrix{
private:
...
protected:
...
public:
...
template<class U>
friend Matrix<U> operator-(const Matrix<U>& lhs, const Matrix<U>& rhs);
};
Here is the function definition:
template <class U>
Matrix<U> operator-(const Matrix<U>& lhs,const Matrix<U>& rhs){
if(lhs.rows != rhs.cols || lhs.rows != rhs.cols){
throw exception();
}
Matrix<U> tmp(lhs.rows, lhs.cols);
for(int i = 0; i < lhs.rows; i++){
for(int j = 0; j < lhs.cols; j++){
tmp.matrix[i][j] = lhs.matrix[i][j]-rhs.matrix[i][j];
}
}
return tmp;
}
works perfect, no warning! Thanks for all the helps
You need to use the template parameters again in the declaration of the temp variable inside:
template <class T>
Matrix<T> operator-(const Matrix<T>& lhs,const Matrix<T>& rhs){
if(lhs.rows != rhs.cols || lhs.rows != rhs.cols{
throw exception();
}
Matrix<T> tmp(lhs.rows, lhs.cols);
for(int i = 0; i < lhs.rows; i++){
for(int j = 0; j < cols; j++){
tmp.matrix[i][j] = lhs.matrix[i][j]+rhs.matrix[i][j];
}
}
return tmp;
}
(change is in Line 5: Matrix<T> tmp(lhs.rows, lhs.cols); )
Members rows, cols are private. Non-class member operator must be a friend of a class. Declare it in the class:
friend Matrix<T> operator-<>(const Matrix<T>& lhs,const Matrix<T>& rhs);
Read this article for more info: Operator overloading : member function vs. non-member function?
Also, this might be a very dumb question, but should the non-member function be in the header file or the .cpp file? So far, everything that I wrote has been in the .h file as they're all templates.
You did it right, all templates must be in a header file. Here is more info: Why can templates only be implemented in the header file?

unable to match function definition to an existing declaration in cpp

I'm doing a course project and I created a matrix class with 2d vector in cpp.
I'm trying to override * operator to an global operator with the matrix obj.
this is my declaration:
friend Matrix<T> operator * (T t, const Matrix<T> &m);
and this is the function:
template <typename T>
Matrix<T> operator * (T t, const Matrix<T> &m)
{
int i, j;
Matrix<T> ans(rows, cols);
for (i = 0; i < rows; i++)
{
for (j = 0; j < rows; j++)
{
ans[i][j] = t * m.mat[i][j];
}
}
return ans;
}
my error is: error C2244: 'Matrix::operator *' : unable to match function definition to an existing declaration
what is wrong with my code??
The friend function you declared, though in class, is not a member function.
Adjust the definition like this:
template <typename T>
Matrix<T> operator * (T t, const Matrix<T> &m)
{
// […]
}

Overloading templated class binary operator*

I'm writing a 2D matrix template to learn templates and some C++11 features.
Wrote the following header:
template <class T, unsigned int Rows, unsigned int Columns>
class Matrix2D
{
private:
array<array<T,Columns>, Rows> m_Matrix;
public:
Matrix2D() {}
array<T,Columns>& operator[](unsigned int row) { return m_Matrix[row]; } ;
const array<T,Columns>& operator[](unsigned int row) const { return m_Matrix[row]; } ;
friend Matrix2D operator+ <> (const Matrix2D &lhs, const Matrix2D &rhs);
friend Matrix2D operator* <> (const Matrix2D &lhs, const Matrix2D &rhs);
};
The operator+ works fine - I have an implementation, it compiles, links, and stepped through with the debugger.
Problem is with operator*, for which I get the compilation error
1>...\matrix2d.h(18): error C2143: syntax error : missing ';' before '<'
1>...\matrix2d.h(19) : see reference to class template instantiation 'Matrix2D<T,Rows,Columns>' being compiled
There's no line of code trying to use the operator, so it's the definition itself which is wrong, I just don't understand why.
Can anyone help?
EDIT: (added from comment)
template <class T, unsigned int Rows, unsigned int Columns>
Matrix2D<T, Rows, Columns> operator+ (const Matrix2D<T, Rows, Columns> &lhs, const Matrix2D<T, Rows, Columns> &rhs)
{
Matrix2D<T, Rows, Columns> addResult;
for (unsigned int i = 0; i < Rows; i++)
for (unsigned int j = 0; j < Columns; j++)
addResult[i][j] = lhs[i][j] + rhs[i][j];
return addResult;
}
template <class T, unsigned int Rows, unsigned int Columns>
Matrix2D<T, Rows, Columns> operator* (const Matrix2D<T, lRows, lColumns> &lhs, const Matrix2D<T, rRows, rColumns> &rhs)
{
Matrix2D<T, lRows, rColumns> mulResult;
for(unsigned int i = 0; i < lRows; i++)
for(unsigned int j = 0; j < rColumns; j++)
for (unsigned int k = 0; k < lColumns; k++)
mulResult[i][k] += lhs[i][k] * rhs[k][j];
return addResult;
}
You cannot friend a specialization of an undeclared template function. Of course, declaring the operators before defining the class template will require you to forward declare it as well:
template <class T, unsigned int Rows, unsigned int Columns>
class Matrix2D;
template <class T, unsigned int Rows, unsigned int Columns>
Matrix2D<T, Rows, Columns>
operator+ (const Matrix2D<T, Rows, Columns> &lhs, const Matrix2D<T, Rows, Columns> &rhs);
template <class T, unsigned int Rows, unsigned int Columns>
Matrix2D<T, Rows, Columns>
operator* (const Matrix2D<T, Rows, Columns> &lhs, const Matrix2D<T, Rows, Columns> &rhs);
template <class T, unsigned int Rows, unsigned int Columns>
class Matrix2D
{
private:
array<array<T,Columns>, Rows> m_Matrix;
public:
Matrix2D() {}
array<T,Columns>& operator[](unsigned int row) { return m_Matrix[row]; }
const array<T,Columns>& operator[](unsigned int row) const { return m_Matrix[row]; }
friend Matrix2D operator+ <> (const Matrix2D &lhs, const Matrix2D &rhs);
friend Matrix2D operator* <> (const Matrix2D &lhs, const Matrix2D &rhs);
};
alternatively, you could take the easy way and define separate operator functions for each specialization of Matrix2D:
template <class T, unsigned int Rows, unsigned int Columns>
class Matrix2D
{
private:
array<array<T,Columns>, Rows> m_Matrix;
public:
Matrix2D() {}
array<T,Columns>& operator[](unsigned int row) { return m_Matrix[row]; }
const array<T,Columns>& operator[](unsigned int row) const { return m_Matrix[row]; }
friend Matrix2D operator+ (const Matrix2D &lhs, const Matrix2D &rhs) {
// do stuff that adds.
}
friend Matrix2D operator* (const Matrix2D &lhs, const Matrix2D &rhs) {
// do stuff that multiplies.
}
};
which I would probably use for the simpler overall syntax.
EDIT: Proper multiplication of non-square matrices means that the operator* function would in fact need to be friends of three different specializations of Matrix2D: the type of the left operand, right operand, and result. I think the first approach herein would become untenable. You should either friend all specializations of operator*:
template <class T, unsigned int Rows, unsigned int Columns>
class Matrix2D
{
// ...
template <typename U, typename V, unsigned Rows, unsigned Common, unsigned Columns>
friend Matrix2D<decltype(std::declval<U>()+std::declval<V>()), Rows, Columns>
operator * (const Matrix2D<U, Rows, Common>&,
const Matrix2D<V, Common, Columns>&);
};
or simply make the data public (probably the best approach for a "collection-of-data" class anyhow).
In:
template <class T, unsigned int Rows, unsigned int Columns>
class Matrix2D
{
// ...
friend Matrix2D operator* <> (const Matrix2D &lhs, const Matrix2D &rhs);
};
Matrix2D refer in fact to Matrix2D<T, Rows, Columns> .
And your operator * should be
template <T, unsigned Rows1, unsigned int Common, unsigned int Column>
Matrix2D<T, Row1, Column> operator* (const Matrix2D<T, Row1, Common>& lhs, const Matrix2D<T, Common, Column>& rhs);

How can I overload the multiplication operator?

I have a Matrix class. I am overloading the multiplication operator, but it's working only if I call Matrixscalar; isn't working for scalarMatrix. How can I fix this?
#include <iostream>
#include <stdint.h>
template<class T>
class Matrix {
public:
Matrix(unsigned rows, unsigned cols);
Matrix(const Matrix<T>& m);
Matrix();
~Matrix(); // Destructor
Matrix<T> operator *(T k) const;
unsigned rows, cols;
private:
int index;
T* data_;
};
template<class T>
Matrix<T> Matrix<T>::operator *(T k) const {
Matrix<double> tmp(rows, cols);
for (unsigned i = 0; i < rows * cols; i++)
tmp.data_[i] = data_[i] * k;
return tmp;
}
template<class T>
Matrix<T> operator *(T k, const Matrix<T>& B) {
return B * k;
}
Edited
I implemented what chill suggested, but I'm getting the following error:
main.cpp: In function ‘int main(int, char**)’:
main.cpp:44:19: error: no match for ‘operator*’ in ‘12 * u2’
main.cpp:44:19: note: candidate is:
lcomatrix/lcomatrix.hpp:149:11: note: template<class T> Matrix<T> operator*(T, const Matrix<T>&)
make: *** [main.o] Error 1
Don't make the operator a member. Define an operator*= as a member of Matrix, then define two free operator*, using *= in their implementation.
Define an operator* outside the class, which just reverses the arguments. And declare the other operator* as const.
template<typename T> Matrix<T> operator* (T k, const Matrix<T> &m) { return m * k; }
The class member operator * operates on it's corresponding object (to the left), invoking M * scalar corresponds to A.operator*(scalar) - this obviously doesn't apply if you switch the order since you don't have operator * defined for the scalar. You can create a global operator * implementation which accepts scalar as first (left) operand and matrix as the second. Inside the implementation switch the order and invoke your inclass class operator *. E.g.:
template <class T>
Matrix<T> operator *(T scalar, const Matrix<T> &M)
{
return M * scalar;
}