Program is not recognizing my overloaded >> and << operators

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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.
Try removing the ostream and istream out of the class
Removing ostream and istream does nothing but create more errors. These must be friend functions of class matrix.
Not true, I removed mine from my class and it worked perfectly and with less headache.. try removing the & from your class

istream& operator>>(istream& in, matrix<T> a)

like so
So I changed the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
 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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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] 
}


No idea what the new error means.
remove them from the class <T> and put them at the top of your main page and see if it persists
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;

}


Consider me a little lost here, I've always had more trouble with C++ than C...

template<class U> friend ostream& operator<<(ostream& out, const matrix<T> &a);
template<class U> friend istream& operator>>(istream& in, matrix<T> &a);

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?

What am I not seeing here.
Last edited on
I think I shall post a matrix template for this forum, almost one of each 3 members here have problem with matrix :-)

@oonej

Not true, I removed mine from my class and it worked perfectly and with less headache.. try removing the & from your class


do you know what is the difference between call by value and call by reference?

please read some thing about them
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... :(
post all your codes may be as a file, I'll see and debug it for you:-)
Last edited on
The matrix.cpp file compiles fine on its own
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'
@ne555
In the case of templates you need to put the definitions in the header, , you can't use a separate cpp


right, however you can use another header file, and include it in your main header file

your class header file
1
2
3
4
5
6
7
8
// your main header ..........

// do some declariation of your class


#include "class_impl.h" // that way


Last edited on
Templates 101.

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...
Last edited on
closed account (o1vk4iN6)
Why do you have a cout message in your operator>> ? When you do:

1
2
float f;
cin >> f;


You don't see it output:

Enter a desired float value:


By doing this you are narrowing the potential usability of that operator. As well there is no way to change where this output is going.
Last edited on
Topic archived. No new replies allowed.