Overloading extraction operator for private two dimensional variable in three dimensional template

I have been having a lot of trouble overriding the extraction operator for my matrices class. The Matrix class is
1
2
3
4
5
6
7
8
9
10
11
12
template<class T,unsigned int ROWS, unsigned int COLUMNS>
class Matrix
{
public:
    Matrix();
    //blah blah blah
    friend ostream& operator <<(ostream&,const Matrix<T,ROWS,COLUMNS>&);
    //I don't need to make nonpartialize this template function, do I?  If so, how do I do it?
    ~Matrix();
private:
    T* M[ROWS];
}

Then there is the code:
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
template<class T,unsigned int H, unsigned int W>
Matrix<T,H,W>::Matrix()			                     // identity matrix
{
	for(int i=0;i<H;i++)
		M[i]=new T[W];
	for(int i=0;i<H;i++)
		for(int j=0;j<W;j++)
			M[i][j]=(i==j)?1:0;
}//this code works JUST FINE
template<class T,unsigned int H,unsigned int W>
Matrix<T,H,W>::~Matrix()
{
	for(int i=0;i<H;i++)
		delete[] M[i];
}
template<class T,unsigned int H,unsigned int W>
ostream& operator<< (ostream& out,const Matrix<T,H,W>& m)

{
	for(int i=0;i<H;i++)
		for(int j=0;j<W;j++)
		{
			char* temp;
			sprintf(temp,"%03d",m.M[i][j]);
			out<<temp;
		}
	return out;
}

Running this, I get the error that m.M is protected, which probably means that I didn't overload the extraction operator properly.
Curiously, I also get the warning
"warning: friend declaration ‘std::ostream& operator<<(std::ostream&, const Matrix<T, ROWS, COLUMNS>&)’ declares a non-template function"
What am I doing wrong?
Last edited on
Add the template args to the ostream declaration and implementation.
Do you mean
1
2
3
4
5
6
7
...
public:
    Matrix();
    //blah blah blah
    template<class T,unsigned int ROWS,unsigned int COLUMNS>
    friend ostream& operator <<(ostream&,const Matrix<T,ROWS,COLUMNS>&);
...

in which case I get an error for redefining T, ROWS, and COLUMNS,
1
2
3
4
5
6
7
...
public:
    Matrix();
    //blah blah blah
    template<class T1,unsigned int ROWS1,unsigned int COLUMNS1>
    friend ostream& operator <<(ostream&,const Matrix<T1,ROWS1,COLUMNS1>&);
...

which also doesn't work (the errors in VC++ and Bluefish don't even match--I prefer Bluefish btw, but I'm stuck with VC++ being at school). Finally, did you mean
 
ostream& operator<< <T,H,W>(ostream& out,const Matrix<T,H,W>& m)

which doesn't work whether I put it in the class or the definition of the member?

I've tried as many combinations of the previous three suggestions as I could think of to no avail. If I haven't touched on what you are saying please clarify. Thank you for your reply!
AFAIK
1
2
template<class T,unsigned int ROWS,unsigned int COLUMNS>
    friend ostream& operator <<(ostream&,const Matrix<T,ROWS,COLUMNS>&);
should work. You could also probably simplify this if rather than have the matrix size set as template arg to set them in a ctor.

What are the errors you get?
Last edited on
With the following code:

Matrix.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
template <class T, unsigned int ROWS, unsigned int COLUMNS>

class Matrix

{

public:

	Matrix();        									// default constructor

        ~Matrix();        									// destructor
        template<class T,unsigned int ROWS,unsigned int COLUMNS>
	        friend ostream& operator << (ostream&,const Matrix<T,ROWS,COLUMNS>&);
protected:
	T* M[ROWS];

};


Matrix.cpp
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
#include "Matrix.h"


template<class T,unsigned int H, unsigned int W>
Matrix<T,H,W>::Matrix()								// identity matrix
{
	for(int i=0;i<H;i++)
		M[i]=new T[W];
	for(int i=0;i<H;i++)
		for(int j=0;j<W;j++)
			M[i][j]=(i==j)?i+j:0;
}
template<class T,unsigned int H,unsigned int W>
Matrix<T,H,W>::~Matrix()
{
	for(int i=0;i<H;i++)
		delete[] M[i];
}
template<class T,unsigned int H,unsigned int W>
ostream& operator<< (ostream& out,const Matrix<T,H,W>& m)

{
	for(int i=0;i<H;i++)
		for(int j=0;j<W;j++)
		{
			char* temp;
			sprintf(temp,"%03d",m.M[i][j]);
			out<<temp;
		}
	return out;
}


Main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
#include "Matrix.cpp"


int main()
{
	cout<<"\nMatrix\n\n";
	
	Matrix<int,3,3> a;
	cout<<a;
	
	cout<<"\n\n";
}


The error is this:

In file included from ./Matrix.cpp:1,
                 from ./Main.cpp:1:
./Matrix.h:16: error: declaration of ‘class T’
./Matrix.h:10: error:  shadows template parm ‘class T’
./Matrix.h:16: error: declaration of ‘unsigned int ROWS’
./Matrix.h:10: error:  shadows template parm ‘unsigned int ROWS’
./Matrix.h:16: error: declaration of ‘unsigned int COLUMNS’
./Matrix.h:10: error:  shadows template parm ‘unsigned int COLUMNS’
./Main.cpp: In function ‘int main()’:
./Main.cpp:9: error: ambiguous overload for ‘operator<<’ in ‘std::cout << a’
./Matrix.cpp:19: note: candidates are: std::ostream& operator<<(std::ostream&, const Matrix<T, H, W>&) [with T = int, unsigned int H = 3u, unsigned int W = 3u]
./Matrix.h:17: note:                 std::ostream& operator<<(std::ostream&, Matrix<T, ROWS, COLUMNS>) [with T = int, unsigned int ROWS = 3u, unsigned int COLUMNS = 3u, T = int, unsigned int ROWS = 3u, unsigned int COLUMNS = 3u]


As for ctoring the dimensions--I want them to be definite and I want to force the user to set them upon initialization--can I do that in ctor? I think I need ctor() before I can have ctor(int rows,int columns).

Thanks again for your quick replies!
Everything should be in the header with templates.
The initializers work, so you must mean the extraction operator--but it must be a nonmember friendly class since we can't overwrite it directly. Do you mean I should move lines 19-35 of Main.cpp into Matrix.h? I will try it but I don't think it will work since we are overloading a member of another class. Or have I misunderstood?
No sorry, I mean everything in Matrix.cpp should be in Matrix.h. So youll have 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
44
45
46
template <class T, unsigned int ROWS, unsigned int COLUMNS>

class Matrix

{

public:

	Matrix();        									// default constructor

        ~Matrix();        									// destructor
        template<class T,unsigned int ROWS,unsigned int COLUMNS>
	        friend ostream& operator << (ostream&,const Matrix<T,ROWS,COLUMNS>&);
protected:
	T* M[ROWS];

};

template<class T,unsigned int H, unsigned int W>
Matrix<T,H,W>::Matrix()								// identity matrix
{
	for(int i=0;i<H;i++)
		M[i]=new T[W];
	for(int i=0;i<H;i++)
		for(int j=0;j<W;j++)
			M[i][j]=(i==j)?i+j:0;
}
template<class T,unsigned int H,unsigned int W>
Matrix<T,H,W>::~Matrix()
{
	for(int i=0;i<H;i++)
		delete[] M[i];
}
template<class T,unsigned int H,unsigned int W>
ostream& operator<< (ostream& out,const Matrix<T,H,W>& m)

{
	for(int i=0;i<H;i++)
		for(int j=0;j<W;j++)
		{
			char* temp;
			sprintf(temp,"%03d",m.M[i][j]);
			out<<temp;
		}
	return out;
}
This is curious; in class we put it in the declarations in an h file and the code in a cpp file.
The following code
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#pragma once


#include <string>

#include <iostream>
#include <cmath>
#include <cstdio>

using namespace std;


template <class T, unsigned int ROWS, unsigned int COLUMNS>

class Matrix

{

public:

	Matrix();        									// default constructor

	~Matrix();        									// destructor
	template<class T,unsigned int ROWS,unsigned int COLUMNS>
	friend ostream& operator << (ostream&,const Matrix<T,ROWS,COLUMNS>&);
protected:
	T* M[ROWS];

};


template<class T,unsigned int H, unsigned int W>
Matrix<T,H,W>::Matrix()								// identity matrix
{
	for(int i=0;i<H;i++)
		M[i]=new T[W];
	for(int i=0;i<H;i++)
		for(int j=0;j<W;j++)
			M[i][j]=(i==j)?i+j:0;
}
template<class T,unsigned int H,unsigned int W>
Matrix<T,H,W>::~Matrix()
{
	for(int i=0;i<H;i++)
		delete[] M[i];
}
template<class T,unsigned int H,unsigned int W>
ostream& operator<< (ostream& out,const Matrix<T,H,W>& m)

{
	for(int i=0;i<H;i++)
		for(int j=0;j<W;j++)
		{
			char* temp;
			sprintf(temp,"%03d",m.M[i][j]);
			out<<temp;
		}
	return out;
}

gives the errors

In file included from ./Main.cpp:1:
./Matrix.h:16: error: declaration of ‘class T’
./Matrix.h:10: error: shadows template parm ‘class T’
./Matrix.h:16: error: declaration of ‘unsigned int ROWS’
./Matrix.h:10: error: shadows template parm ‘unsigned int ROWS’
./Matrix.h:16: error: declaration of ‘unsigned int COLUMNS’
./Matrix.h:10: error: shadows template parm ‘unsigned int COLUMNS’


So I tried removing the bold:
1
2
        template<class T,unsigned int ROWS,unsigned int COLUMNS>
	        friend ostream& operator << (ostream&,const Matrix<T,ROWS,COLUMNS>&);

and got a stream of much more interesting errors

In file included from ./Main.cpp:1:
./Matrix.h:16: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, const Matrix<T, ROWS, COLUMNS>&)’ declares a non-template function
./Matrix.h:16: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
/tmp/ccLbNKsK.o: In function `main':
Main.cpp:(.text+0x3b): undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Matrix<int, 3u, 3u> const&)'
collect2: ld returned 1 exit status

I think your code should stay lol
But what do I do about the errors?

In file included from ./Main.cpp:1:
./Matrix.h:16: error: declaration of ‘class T’
./Matrix.h:10: error: shadows template parm ‘class T’
./Matrix.h:16: error: declaration of ‘unsigned int ROWS’
./Matrix.h:10: error: shadows template parm ‘unsigned int ROWS’
./Matrix.h:16: error: declaration of ‘unsigned int COLUMNS’
./Matrix.h:10: error: shadows template parm ‘unsigned int COLUMNS’

I just got really excited when g++ compiled
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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#pragma once


#include <string>

#include <iostream>
#include <cmath>
#include <cstdio>

using namespace std;


template <class T, unsigned int ROWS, unsigned int COLUMNS>

class Matrix

{

public:

	Matrix();        									// default constructor

	~Matrix();        									// destructor
	template<class T1,unsigned int ROWS1,unsigned int COLUMNS1>
	friend ostream& operator << (ostream&,const Matrix<T1,ROWS1,COLUMNS1>&);
protected:
	T* M[ROWS];

};


template<class T,unsigned int H, unsigned int W>
Matrix<T,H,W>::Matrix()								// identity matrix
{
	for(int i=0;i<H;i++)
		M[i]=new T[W];
	for(int i=0;i<H;i++)
		for(int j=0;j<W;j++)
			M[i][j]=(i==j)?i+j:0;
}
template<class T,unsigned int H,unsigned int W>
Matrix<T,H,W>::~Matrix()
{
	for(int i=0;i<H;i++)
		delete[] M[i];
}
template<class T,unsigned int H,unsigned int W>
ostream& operator<< (ostream& out,const Matrix<T,H,W>& m)

{
	for(int i=0;i<H;i++)
		for(int j=0;j<W;j++)
		{
			char* temp;
			sprintf(temp,"%03d",m.M[i][j]);
			out<<temp;
		}
	return out;
}

(changed parts in bold) but the output is

Matrix

Segmentation fault

hmph :/
char* temp
In your extraction operator overload doesn't point to any memory.
THAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANK YOUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU!!!!!!!
Topic archived. No new replies allowed.