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)
{
// […]
}
Related
I have a big problem in my C++ Code example. There is something wrong with 'friend' and the 'template'.
Error Messages:
Matrix.h:26:79: warning:
friend declaration 'std::ostream&
matrixClass::operator<<(std::ostream&, const matrixClass::Matrix&)'
declares a non-template function [-Wnon-template-friend]
friend std::ostream &operator<<(std::ostream&, const Matrix &matrix);
Matrix.h:26:79: note:
(if this is not what you intended, make sure the function template
has already been declared and add <> after the function name here)
Matrix.h:28:77: warning:
friend declaration 'matrixClass::Matrix<T>*
matrixClass::operator*(const matrixClass::Matrix&, const
matrixClass::Matrix&)' declares a non-template function
[-Wnon-template-friend]
friend Matrix* operator*(const Matrix &m1, const Matrix &m2);
Matrix.cpp:1:0:
C:\Users\Peter\CLionProjects\PK\untitled76\Matrix.h:26:79: warning:
friend declaration 'std::ostream&
matrixClass::operator<<(std::ostream&, const matrixClass::Matrix&)'
declares a non-template function [-Wnon-template-friend]
friend std::ostream &operator<<(std::ostream&, const Matrix &matrix);
Matrix.h:26:79: note:
(if this is not what you intended, make sure the function template
has already been declared and add <> after the function name here)
Matrix.h:28:77: warning:
friend declaration 'matrixClass::Matrix<T>*
matrixClass::operator*(const matrixClass::Matrix&, const
matrixClass::Matrix&)' declares a non-template function
[-Wnon-template-friend]
friend Matrix* operator*(const Matrix &m1, const Matrix &m2);
CMakeFiles\untitled76.dir/objects.a(main.cpp.obj): In function `main':
main.cpp:8: undefined reference to
main.cpp:8: undefined reference to matrixClass::Matrix<int>::Matrix(int)'<br>
main.cpp:10: undefined reference tomatrixClass::Matrix::set(int, int, int)'
main.cpp:11: undefined reference to matrixClass::Matrix<int>::set(int, int, int)'<br>
main.cpp:12: undefined reference tomatrixClass::Matrix::set(int, int, int)'
main.cpp:13: undefined reference to matrixClass::Matrix<int>::set(int, int, int)'<br>
main.cpp:15: undefined reference tomatrixClass::operator<<(std::ostream&, matrixClass::Matrix const&)'
main.cpp:15: undefined reference to matrixClass::operator<<(std::ostream&, matrixClass::Matrix<int> const&)'<br>
main.cpp:8: undefined reference tomatrixClass::Matrix::~Matrix()'
main.cpp:8: undefined reference to `matrixClass::Matrix::~Matrix()'
Code:
Matrix.h
#ifndef MATRIX_H_
#define MATRIX_H_
#include <iostream>
namespace matrixClass {
template<class T>
class Matrix {
private:
int dimension;
T **m;
public:
Matrix(int d);
Matrix(const Matrix &original);
~Matrix();
void set(int x, int y, T value);
T get(int x, int y) const;
int getDimension() const;
friend std::ostream &operator<<(std::ostream&, const Matrix<T> &matrix);
friend Matrix<T>* operator*(const Matrix<T> &m1, const Matrix<T> &m2);
};
}
#endif
Matrix.cpp
#include "Matrix.h"
using namespace matrixClass;
template<class T>
Matrix<T>::Matrix(int d)
: dimension{d}, m{new T *[d]} {
//m = new T*[d];
for (int i = 0; i < d; i++) {
m[i] = new T[d];
}
}
// COPY-CONSTRUCTOR
template<class T>
Matrix<T>::Matrix(const Matrix &original)
: dimension{original.dimension},
m{new T *[original.dimension]} {
for (int i = 0; i < dimension; i++) {
*(m + i) = *(original.m + i);
}
}
// DESTRUCTOR
template<class T>
Matrix<T>::~Matrix() {
for (int i = 0; i < dimension; i++) {
delete[] m[i];
}
delete[] m;
}
template<class T>
void Matrix<T>::set(int x, int y, T value) {
m[x][y] = value;
}
template<class T>
T Matrix<T>::get(int x, int y) const {
return m[x][y];
}
template<class T>
int Matrix<T>::getDimension() const {
return dimension;
}
template<class T>
std::ostream& operator<<(std::ostream& output, const Matrix<T>& matrix) {
int dimension = matrix.getDimension();
for(int x = 0; x < dimension; x++) {
for(int y = 0; y < dimension; y++) {
output << matrix.get(x, y) << " ";
}
return output;
}
}
template<class T>
Matrix<T>* operator*(const Matrix<T>& m1, const Matrix<T>& m2) {
int dimension = m1.getDimension();
Matrix<T>* m = new Matrix<T>(dimension);
for(int x = 0; x < dimension; x++) {
for(int y = 0; y < dimension; y++) {
T value = 0;
for(int i = 0; i < dimension; i++) {
value += m1.get(x, i) * m2.get(i, y);
}
m->set(x, y, value);
}
}
return m;
}
main.cpp
#include <iostream>
#include "Matrix.h"
using namespace matrixClass;
using namespace std;
int main() {
Matrix<int> m(2);
m.set(0, 0, 1);
m.set(0, 1, 2);
m.set(1, 0, 3);
m.set(1, 1, 4);
cout << m << "*" << endl << m << "=" << endl;
return 0;
}
In friend declaration operator<< refers to a non-template function, while its definition says it's a template function; they don't match.
You can define it inline with the friend declaration (as non-template function):
template<class T>
class Matrix {
... ...
friend std::ostream& operator<<(std::ostream& output, const Matrix<T>& matrix) {
int dimension = matrix.getDimension();
for(int x = 0; x < dimension; x++) {
for(int y = 0; y < dimension; y++) {
output << matrix.get(x, y) << " ";
}
return output;
}
}
... ...
};
Or make the friend declaration referring to the function template:
// class declaration
template<class T>
class Matrix;
// function declaration
template<class T>
std::ostream& operator<<(std::ostream& output, const Matrix<T>& matrix);
// class definition
template<class T>
class Matrix {
... ...
friend std::ostream& operator<< <T>(std::ostream& output, const Matrix<T>& matrix);
... ...
};
// function definition
template<class T>
std::ostream& operator<<(std::ostream& output, const Matrix<T>& matrix) {
int dimension = matrix.getDimension();
for(int x = 0; x < dimension; x++) {
for(int y = 0; y < dimension; y++) {
output << matrix.get(x, y) << " ";
}
return output;
}
}
And about the undefined reference error, see Why can templates only be implemented in the header file?
This answer addresses the problem with your non-member operator<<() and operator*() using Friend Templates, which is slightly different from making an instance of a function template a friend (the second solution presented by #songyuanyao). The difference is that with a Friend Template, all instances of the template function are friends of the class Matrix<>. In this case, I don't think there is any practical difference, but in others, there may be. Therefore, I figured I'd present it anyway.
I think about it like this. Both operators are non-member functions which means they are independent from the class Matrix<>, so think of their prototypes independently:
template<class T>
std::ostream& operator<<(std::ostream& output, const Matrix<T>& matrix);
template<class T>
Matrix<T>* operator*(const Matrix<T>& m1, const Matrix<T>& m2);
Now, replace T with U because to make all instances of them friends of Matrix<>, their prototype needs to be included in the class definition for Matrix<> which is also a template, and it is already using T as its template parameter.
template<class U>
std::ostream& operator<<(std::ostream& output, const Matrix<U>& matrix);
template<class U>
Matrix<U>* operator*(const Matrix<U>& m1, const Matrix<U>& m2);
Now, you can make them friends of Matrix<>. All you need is the appropriate syntax:
template<class T>
class Matrix
{
...
template<class U>
friend std::ostream &operator<<(std::ostream&, const Matrix<U> &matrix);
template<class U>
friend Matrix<U>* operator*(const Matrix<U> &m1, const Matrix<U> &m2);
};
Finally, they all need to be within the matrixClass namespace, and their declarations and definitions need to be in the right order so that everyone know the others exists:
namespace matrixClass {
// BEGIN Forward declarations
template<class T>
class Matrix;
template<class U>
std::ostream &operator<<(std::ostream&, const Matrix<U> &matrix);
template<class U>
Matrix<U>* operator*(const Matrix<U> &m1, const Matrix<U> &m2);
// END Forward declarations
template<class T>
class Matrix
{
...
template<class U>
friend std::ostream &operator<<(std::ostream&, const Matrix<U> &matrix);
template<class U>
friend Matrix<U>* operator*(const Matrix<U> &m1, const Matrix<U> &m2);
};
...
template<class U>
std::ostream& operator<<(std::ostream& output, const Matrix<U>& matrix)
{
... // your implementation goes here
}
template<class U>
Matrix<U>* operator*(const Matrix<U>& m1, const Matrix<U>& m2)
{
... // your implementation goes here
}
} // end of namespace matrixClass
All this template code should be in the header file, Matrix.h, as it has already been mentioned.
Also, I think that you should change the prototype of operator*() to return Matrix<U> instead of Matrix<U>*. It will behave more like the normal operator*(), and it'll enable you to do things like: Matrix<int> m = m1*m2; or m = m1*m2*m3;. Additionally, the users of your class won't have to worry about deleting the memory allocated by operator*() or the performance cost of the dynamic allocation. Just create a local Matrix<U> variable in operator*() and return it by value; let Return Value Optimization (RVO) take care of the rest.
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?
I have a 3x3 Matrix and a 3x1 Vector classes. I have two multiplication operators; one for multiplying a matrix with a scalar, another for multiplying a matrix with a vector object. The matrix-scalar multiplication operator is member inside the Matrix class and the matrix-vector multiplication operator is global.
#include <initializer_list>
#include <array>
template <class T>
class Matrix
{
public:
Matrix(std::initializer_list<T> List);
Matrix() : Matrix({0,0,0,0,0,0,0,0,0}) {}
template <class S> // THE COMPILER TRIES TO USE
Matrix<T> operator*(const S & Scalar); // THIS OPERATOR IN BOTH CASES.
const T & operator()(size_t i, size_t j) const;
private:
static constexpr size_t SIZE = 3;
static constexpr size_t AREA = SIZE * SIZE;
std::array<T, AREA> E;
};
template <class T>
Matrix<T>::Matrix(std::initializer_list<T> List)
{
if (List.size() != AREA) throw("Error!");
for (size_t i=0; i<AREA; i++)
{
E[i] = *(List.begin() + i);
}
}
template <class T>
const T & Matrix<T>::operator()(size_t i, size_t j) const
{
return E[SIZE * j + i];
}
template <class T>
template <class S>
Matrix<T> Matrix<T>::operator*(const S & Scalar)
{
const T ScalarT = static_cast<T>(Scalar);
Matrix<T> Result;
for (size_t i=0; i<AREA; i++)
{
Result.E[i] = E[i] * ScalarT;
}
return Result;
}
template <class T>
class Vector
{
public:
Vector(std::initializer_list<T> List);
Vector() : Vector({0,0,0}) {};
const T & operator()(size_t i) const;
T & operator()(size_t i);
private:
static constexpr size_t SIZE = 3;
std::array<T, SIZE> E;
};
template <class T>
Vector<T>::Vector(std::initializer_list<T> List)
{
if (List.size() != SIZE) throw("Error!");
for (size_t i=0; i<SIZE; i++)
{
E[i] = *(List.begin() + i);
}
}
template <class T>
const T & Vector<T>::operator()(size_t i) const
{
return E[i];
}
template <class T>
T & Vector<T>::operator()(size_t i)
{
return E[i];
}
template <class T> // THE COMPILER NEVER TRIES USING THIS GLOBAL OPERATOR.
Vector<T> operator*(const Matrix<T> & Mat, const Vector<T> & Vec)
{
Vector<T> Result;
Result(0) = Mat(0,0) * Vec(0) + Mat(0,1) * Vec(1) + Mat(0,2) * Vec(2);
Result(1) = Mat(1,0) * Vec(0) + Mat(1,1) * Vec(1) + Mat(1,2) * Vec(2);
Result(2) = Mat(2,0) * Vec(0) + Mat(2,1) * Vec(1) + Mat(2,2) * Vec(2);
return Result;
}
int wmain(int argc, wchar_t *argv[]/*, wchar_t *envp[]*/)
{
Matrix<float> Mat1({2, 0, 0,
0, 2, 0,
0, 0, 2});
Vector<float> Vec1({1,
2,
3});
Matrix<float> Mat2 = Mat1 * 2; // Matrix-Scalar Multiplication
Vector<float> Vec2 = Mat1 * Vec1; // Matrix-Vector Multiplication
return 0;
}
The problem is, when I try to do a matrix-vector multiplication, the compiler chooses and tries to use the matrix-scalar multiplication operator, and gives a compiler error.
If I delete the matrix-scalar multiplication operator and the line where I use it, the program runs successfully. In reverse, if I delete the matrix-vector multiplication operator, it again runs successfully. They just don't get along. And when it runs (in either case), it makes the all calculations correctly.
What is going wrong here?
Compiler & IDE: Microsoft Visual Studio 2015 Community Edition
The language doesn't specify that when searching for overloads to examine all possible scopes. As soon as one candidate is found, only the overloads in that scope are used to select the best candidate. If that candidate fails to compile for other reasons, it still won't examine additional scopes.
So in your case since the scalar is a template parameter it will match any type so as long as the left-hand operand of the operator is a Matrix<T>, the scalar multiplication will match any right-hand operand.
You could:
Just make both operator* at the same scope so they're both considered for overload resolution.
Change the scalar operator to take for example a Scalar<T> that's a thin wrapper around a scalar type rather than a generic template type.
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.
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;
}