Vladimir Grigoriev wrote:
Quote
Hi
I have an interface file with template class definition. This class
definition contains a friend function
friend ostream & operator<<( ostream & outs, const List<ItemType>&
theList );
That friend declaration is for a *non-template* function. E.g., for
List<int>, that declares the non-template function "ostream &
operator<<( ostream & outs, const List<int>& theList)" to be a friend.
It also declares that function to be visible via argument dependent
lookup on List<int>.
Quote
Also I have a realization file with the following function definition
template <typename ItemType>
ostream & operator<<( ostream & outs, const List<ItemType>& theList )
{
for ( int i = 0; i < theList.current_length; i++ )
outs << theList.item[i] << endl;
return outs;
}
That's independent of the friend declaration above.
Quote
And at last in main program there is
cout << "first_list = \n" << first_list;
That finds the non-template function declared in the friend declaration
via ADL as well as the template defined above, and picks the
non-template since non-templates always beat templates in overload
resolution.
Quote
But when I build the corresponding project (BCB 5.0) I get linker error
[Linker Error] Unresolved external
"listsavitch::operator<<(std::basic_ostream(char, std::....
What is wrong?
You never defined the non-template friend. There are two solutions.
1. Define the non-template functions:
friend ostream & operator<<( ostream & outs, const List<ItemType>&
theList )
{
for ( int i = 0; i < theList.current_length; i++ )
outs << theList.item[i] << endl;
return outs;
}
Note that the only way to do this is to define the function inline
inside the class body.
2. Make the relevent template specialization a friend, and don't declare
the non-template:
//fwd declarations are necessary:
template <typename ItemType>
class List;
template <typename ItemType>
ostream & operator<<( ostream & outs, const List<ItemType>& theList);
//you could put operator<< definition here, before List definition,
//thanks to two phase name lookup. I haven't, for clarity.
template <typename ItemType>
class List
{
//...
//Note the <ItemType>on the line below:
friend ostream & operator<< <ItemType>( ostream & outs, const
List<ItemType>& theList);
};
template <typename ItemType>
ostream & operator<<( ostream & outs, const List<ItemType>& theList)
{
//put definition here as before.
}
1 is good in that it is supported even by quite old compilers, whereas 2
requires a reasonably standards compliant compiler.
Tom