I have a program that utilizes a simple class matrix<T>. I have overloaded the operators for >> and << as below. These are friend functions declared in the matrix class.
template<class U> friend ostream& operator<<(ostream& out, const matrix<T> &a);
template<class U> friend istream& operator>>(istream& in, matrix<T> &a);
//overload for <<, prints out the contents of the matrix
template <class T>
ostream& operator<< (ostream& out, const matrix<T> &a)
{
out << "[";
for(int i = 0; i<a.rows; i++){
for(int j = 0; j<a.cols; j++)
{ out << a.arr[i][j] << " "; }
out << "\n";
}
out << "]";
return out;
}
//overload for input operator >>, takes user input and
//creates a matrix with given values
template <class T>
istream& operator>>(istream& in, matrix<T> &a)
{
cout << "\nEnter the desired values for the matrix in the for [ x y ... ],\n"
<< "where x is the number of rows, y is the number of columns, followed\n"
<< "by the values by row.\n\n";
char temp;
int r, c;
in >> temp;
in >> r >> c;
a.resize(r, c);
for(int i = 0; i<r; i++){
for(int j = 0; j<c; j++)
{ in >> a.arr[i][j]; }
}
in >> temp;
return in;
}
The matrix.cpp file compiles fine on its own. When I try to compile with a test main, I get ridiculous errors. The problem is whenever I try to use >> or << with a matrix object. For example, the line
cin >> a;
or
cout << a;
give an error "no match for ‘operator>>’ in ‘std::cin >> a’". It then lists all the candidates for istream and ostream in a big mess. What am I doing wrong here? The main does not seem to be recognizing the overloaded operators << and >> for use with objects of type matrix.
template<class T> ostream& operator<<(ostream& out, const matrix<T> a);
template<class T> istream& operator>>(istream& in, matrix<T> a);
//overload for <<, prints out the contents of the matrix
template<class T>
ostream& operator<< (ostream& out, const matrix<T> a)
{
out << "[";
for(int i = 0; i<a.rows; i++){
for(int j = 0; j<a.cols; j++)
{ out << a.arr[i][j] << " "; }
out << "\n";
}
out << "]";
return out;
}
//overload for input operator >>, takes user input and
//creates a matrix with given values
template<class T>
istream& operator>>(istream& in, matrix<T> a)
{
cout << "\nEnter the desired values for the matrix in the for [ x y ... ],\n"
<< "where x is the number of rows, y is the number of columns, followed\n"
<< "by the values by row.\n\n";
char temp;
int r, c;
in >> temp;
in >> r >> c;
a.resize(r, c);
for(int i = 0; i<r; i++){
for(int j = 0; j<c; j++)
{ in >> a.arr[i][j]; }
}
in >> temp;
return in;
}
Now the large horrible error is gone, but is replaced with a new error:
Undefined symbols:
"std::basic_istream<char, std::char_traits<char> >& operator>><int>(std::basic_istream<char, std::char_traits<char> >&, matrix<int>)", referenced from:
Test1() in ccgb7Pux.o
Test1() in ccgb7Pux.o
"std::basic_ostream<char, std::char_traits<char> >& operator<< <int>(std::basic_ostream<char, std::char_traits<char> >&, matrix<int>)", referenced from:
Test1() in ccgb7Pux.o
Test1() in ccgb7Pux.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
Test1() is the test function that runs in main. As below:
void Test1()
{
matrix<int> a, b; //Two empty matrices are created
cout << a.numrows() << " " << a.numcols() << endl; // yields 0 0
cin >> a; // User types [3 3 1 2 3 6 5 4 9 8 10]
// This will create a 3 by 3 matrix
// The first input is the number of rows, and the
// second is the number of columns.
// The rest are the values inserted row by row
cout << a; // Output should be
// [1 2 3
// 6 5 4
// 9 8 10]
cin >> b; // User types [3 2 9 1 2 3 4 5]
cout << b; // Output should be
// [9 1
// 2 3
// 4 5]
}
I made the suggested changed and now receive this error on my resize(int,int) function:
Undefined symbols:
"matrix<int>::resize(int, int)", referenced from:
std::basic_istream<char, std::char_traits<char> >& operator>><int>(std::basic_istream<char, std::char_traits<char> >&, matrix<int>)in ccdlsGl6.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
Resize is a member function of class matrix , implemented below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
//function to resize the array of an already declared Matrix object
template<class T>
void matrix<T>::resize(int r, int c)
{
//clean old contents of memory
for(int i = 0; i<rows; i++)
delete [] arr[i];
delete [] arr;
//allocate new memory
arr = new T*[r];
for(int i = 0; i<r; i++)
arr[i] = new T[c];
rows = r;
cols = c;
}
The class is using U as the class template variable, but you use T in the parameter call. Shouldn't the U be T so it is used in the function prototype?
I do indeed, but what I dont understand is why my overload operator << would give some ridiculous errors with call by reference but not by call by value... :(
That's the problem.
In the case of templates you need to put the definitions in the header, you can't use a separate cpp*
For the friend declaration http://stackoverflow.com/a/4138435
* Actually, you can (sort of). Look 'explicit template instantiation'
1) If the template method is used anywhere else besides the implementing class/.cpp then the template implementation must be in a header.
2) If however, the template is lets say a private method, then it can be implemented in the source file (This works for protected and public as well as long as it doesn't break rule number 1).
Based on this void matrix<T>::resize(int r, int c) you are violating rule number 1.
I've overly simplified how templates can be defined...