operator overloading in templates

  • Thread starter Christian Christmann
  • Start date
C

Christian Christmann

Hi,

I added an operator overloader in my template
class:

graph.h:

template <class NODE>
class Node
{
friend ostream &operator<< (ostream &, Node<NODE> &); //line 80
NODE* info;
[snip]
}

graph.cpp:
[snip]
template <class NODE>
ostream &operator<<(ostream &output, const Node<NODE> &node)
{
output << *(node.info) << " ";
return ouput;
}
[snip}


While compiling with gcc I get the warning:
In file included from graph.cpp:2:
.../graph.h:80: warning: friend declaration `std::eek:stream&
operator<<(std::eek:stream&, Node<NODE>&)' declares a
non-template function
.../graph.h:80: warning: (if this is not what you intended, make sure the
function template has already been declared and add <> after the
function name here) -Wno-non-template-friend disables this warning

What is the reason for that warning and how can I avoid it?

Thank you.

Regards,
Chris
 
V

Victor Bazarov

Christian said:
I added an operator overloader in my template
class:

graph.h:

Add here:

template<class NODE> class Node;
template<class NODE> ostream& operator<<(ostream&, Node<NODE>&);

And, is there any particular reason why your operator<< needs it second
argument as a reference to a *non-const* Node said:
template <class NODE>
class Node
{
friend ostream &operator<< (ostream &, Node<NODE> &); //line 80
NODE* info;
[snip]
}

graph.cpp:
[snip]
template <class NODE>
ostream &operator<<(ostream &output, const Node<NODE> &node)
{
output << *(node.info) << " ";
return ouput;
}
[snip}


While compiling with gcc I get the warning:
In file included from graph.cpp:2:
../graph.h:80: warning: friend declaration `std::eek:stream&
operator<<(std::eek:stream&, Node<NODE>&)' declares a
non-template function
../graph.h:80: warning: (if this is not what you intended, make sure the
function template has already been declared and add <> after the
function name here) -Wno-non-template-friend disables this warning

What is the reason for that warning and how can I avoid it?

Declare your operator<< as a template before the class template. See
above.

V
 
D

David White

Victor Bazarov said:
Add here:

template<class NODE> class Node;
template<class NODE> ostream& operator<<(ostream&, Node<NODE>&);

Why are these declarations necessary? I notice that neither VS 2003 nor VC++
6.0 needs them.
template <class NODE>
class Node
{
friend ostream &operator<< (ostream &, Node<NODE> &); //line 80
NODE* info;
[snip]
}

graph.cpp:
[snip]
template <class NODE>
ostream &operator<<(ostream &output, const Node<NODE> &node)
{
output << *(node.info) << " ";
return ouput;
}
[snip}

DW
 
V

Victor Bazarov

David said:
Why are these declarations necessary? I notice that neither VS 2003 nor VC++
6.0 needs them.

The Standard, in 14.5.3/1, says that if the friend function declaration
that is not a template declaration (does not begin with the 'template'
keyword) and the name of the function is a template-id, the friend
declaration refers to a template specialisation, if it's not a template-id
but an 'unqualified-id', it declares an ordinary function. So, if you (or
the OP) don't declare operator<< as a template beforehand, it is
considered a simple function, which goes against the fact that its second
argument depends on 'NODE'.

The conflict is resolved if 'operator<<' is a template-id, which is
achieved by declaring 'operator<<' a template (that's the second template
declaration above 'Node'). The declaration of 'Node' as a class template
(the very first declaration statement) is necessary because it's used in
the following function template declaration.
template <class NODE>
class Node
{
friend ostream &operator<< (ostream &, Node<NODE> &); //line 80
NODE* info;
[snip]
}

graph.cpp:
[snip]
template <class NODE>
ostream &operator<<(ostream &output, const Node<NODE> &node)
{
output << *(node.info) << " ";
return ouput;
}
[snip}


DW

V
 
C

Christian Christmann

Add here:

template<class NODE> class Node;
template<class NODE> ostream& operator<<(ostream&, Node<NODE>&);


After adding the two lines before the class declaration and compiling I
still get the same error message.
And, is there any particular reason why your operator<< needs it second
argument as a reference to a *non-const* Node<>?

What would you suggest instead?

Thank you.

Chris
 
V

Victor Bazarov

Christian said:
After adding the two lines before the class declaration and compiling I
still get the same error message.

FAQ 5.8.
What would you suggest instead?

A reference to a *const* Node<>. Or does your output operator actually
change the Node?

V
 
C

Christian Christmann

Sorry, but I don't really know what I did wrong. The message I get is the
same as in my first post:

graph.h:83: warning: friend declaration `std::eek:stream&
operator<<(std::eek:stream&, Node<NODE>&)' declares a
non-template function
graph.h:83: warning: (if this is not what you intended, make sure the
function template has already been declared and add <> after the function name
here) -Wno-non-template-friend disables this warning


If you expect something else, please let me know.

A reference to a *const* Node<>. Or does your output operator actually
change the Node?

No, Node is not going to be changed. So, you mean defining Node as const ?



Chris
 
D

David White

Victor Bazarov said:
The Standard, in 14.5.3/1, says that if the friend function declaration
that is not a template declaration (does not begin with the 'template'
keyword) and the name of the function is a template-id, the friend
declaration refers to a template specialisation, if it's not a template-id
but an 'unqualified-id', it declares an ordinary function. So, if you (or
the OP) don't declare operator<< as a template beforehand, it is
considered a simple function, which goes against the fact that its second
argument depends on 'NODE'.

The conflict is resolved if 'operator<<' is a template-id, which is
achieved by declaring 'operator<<' a template (that's the second template
declaration above 'Node'). The declaration of 'Node' as a class template
(the very first declaration statement) is necessary because it's used in
the following function template declaration.

It will take me a while to get my head around this. I thought the friend
declaration in the class definition looked unambiguously like a template for
the friend function (for the reason you pointed out; the second argument
contains the template parameter NODE), and that seems to be how my compilers
interpreted it. A member function in a class template might have a template
parameter among its arguments too. Anyway, thanks for the explanation.

DW
 
V

Victor Bazarov

Christian said:
[..]> Sorry, but I don't really know what I did wrong. The message I get
is
the
same as in my first post:
[..]

I don't know what to tell you. Try using a later version of the compiler.

V
 
Z

Zaharije Pasalic

Victor Bazarov said:
Christian said:
[..]> Sorry, but I don't really know what I did wrong. The message I get
is
the
same as in my first post:
[..]

I don't know what to tell you. Try using a later version of the compiler.

V

/*
I posted something same few months ago and only solution that I can
find is something like this:

template <typename T> class K {
T p;
public:
friend ostream& operator<< <T>(ostream&, K<T>&);
};

template <typename T> ostream& operator<<(ostream& c, K<T> &k)
{
return cout << k.podatak;
}

Note1: this code will not work on all compilers (at least Borland C++
5.0 issue error on this), gcc 3.2 compile above code OK. If you use
Borland 5.0 you must implement operator in class body and remove <T>
after operator <<.

Note2: it works with "const K<T>&"

Best,
Zaharije Pasalic
*/
#include <iostream>

using namespace std;

template <typename T> class Klasa
{
T podatak;
public:
friend ostream& operator<< <T>(ostream&, const
Klasa<T>&);
};

template <typename T> ostream& operator<<(ostream& c, const Klasa<T>
&k)
{
return cout << k.podatak;
}

int main() {
Klasa<int> a;
cout << a;
return 0;
}
 
C

Christian Christmann

Christian said:
[..]> Sorry, but I don't really know what I did wrong. The message I get
is
the
same as in my first post:
[..]

I don't know what to tell you. Try using a later version of the compiler.

I could fix the problem. What I had to do was to add <> in the header
file. The declaration of the operator has to be:
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,662
Latest member
salsusa

Latest Threads

Top