Error when overloading operator<< for a template

Hi everyone, I'm writing a template Matrix and I want to overload operator<< so that users can write cout << myMatrix; in the future.

It is a friend operator. When I write the implementation
1
2
template <class T>
ostream& operator<< (ostream& output, const Matrix<T>& theMatrix)

I get the error
expected constructor, destructor, or type conversion before '&' token


Am I using wrong syntax?


Thanks in advance.

Duh, silly me. I forgot to put std:: somewhere.

My concern remains:

Btw, the declaration is as
1
2
template <T>
friend std::ostream& operator<< (std::ostream&, const Matrix<T>&);

If I omit the template <T> the compiler gives me warning that I'm creating a non-template function.

I read from a book that for some compilers, we have to add the line template <class T>, but my compiler complains that this shadows template parm 'class T'.

When I change it to template <T> it doesn't give me errors, but is it the right way?

(I'm using Dev-C++, it uses g++ to compile)
Last edited on
No, that looks wrong.

 
template< typename T > friend std::ostream& operator<<( std::ostream&, const Matrix<T>& );


does not work?

I noticed you did not have the namespace std:: on your first parameter.
I noticed you did not have the namespace std:: on your first parameter

My mistake again...forgot to change that line when editing =\

When I write <class T> or <typename T> in the declaration the compiler says
declaration of 'class T' shadows template parm 'class T'
Last edited on
Can you post the code and actual compile error?
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
template <class T>
class Matrix
{
   public:
     // constructors
     Matrix();
     Matrix(unsigned int m, unsigned int n);
     Matrix(const Matrix&);
     virtual ~Matrix() {}       // class SqMatrix inheriting from this...
     
     // overloaded operators
        // assignment
        Matrix& operator= (const Matrix& rhs);
        
        // assessment
        T&       operator() (unsigned int i, unsigned int j);
        const T& operator() (unsigned int i, unsigned int j) const;
        
        // insertion
        template <class T>
        friend std::ostream& operator<< (std::ostream&, Matrix<T>&);  // <-----
        
        // arithmatics
        Matrix<T> operator+ (const Matrix<T>&);
        Matrix<T> operator- (const Matrix<T>&);
        // blablabla...

   protected:
     std::vector< std::vector<T> > itsData;
};


(I edited the line numbers so that they are consistent here)
On line 20,
Writing <class T> or <typename T> it says
20: declaration of 'class T'
1: shadows template parm 'class T'

Writing just <T> compiles fine...

Without line 20 it warns me that I'm declaring a non-template function, this is expected.


Btw, I wonder if the return type should be Matrix or Matrix<T> on line 24,25; and what is the difference?
Last edited on
Oh, actually that's a good point. Because it is a template class, you should be able to write

 
friend std::ostream& operator<<( std::ostream&, const Matrix& );


You don't actually need the function to be explicitly templated since it already is templated by virtue of the template class. I think that will solve the problem.

And to answer your question, since the class is templated, writing Matrix tells the compiler that you really mean Matrix<T> where T is the type the class was instantiated with.

Typically, you'd do something like:

1
2
template< typename U >
Matrix operator+( const Matrix<U>& ) const;


(Note use of U and not T)

to allow the user to add a matrix instantiated with a different type. For example, the above declaration would allow the following to compile:

1
2
3
4
Matrix<double> a;
Matrix<int> b;

cout << ( a + b );  // calls operator+(const Matrix<U>& ) const [with U = int] 






Now I see thanks very much.

Ah, I probably worried too much about the warning...

That explains a lot. So T is the thing to tell the compiler whereas U is "left for users to fill in".

I may post if I find further problems =P actually I haven't started writing a real .cpp to test it.
What should be in the definition? Are there two "parameters" T and U?

1
2
3
4
5
template <typename ?>
Matrix<?> operator+(const Matrix<?>&) const
{
   // ...
}
To clarify and answer your question:

given a template class:

1
2
3
template< typename Foobar >
class C {
};


now anywhere you want to reference a C, technically you have to write C<some-type>, right?

But the language allows you to be a little lazier inside the class:

1
2
3
4
5
template< typename Foobar >
class C {
  public:
       void frobnicate( const C& );
};


Note in the declaration it just says "C". But technically this is impossible, because C is a template class. The language allows this and defines this implicitly to mean C<Foobar>. (There is nothing magical about 'T' or 'U').

But what if you didn't want it to mean C<Foobar>? Then you'd do:

1
2
3
4
5
6
template< typename Foobar >
class C {
  public:
       template< typename SomeOtherType >
       void frobnicate( const C<SomeOtherType>& );
};


It might be that SomeOtherType == Foobar, or it might not. Either way would compile as far as this declaration is concerned.
Thanks that makes it clear :)
Topic archived. No new replies allowed.