By declaring the operator friend, you tell the compiler to look for a function
ostream& operator<<(ostream &,T);
where T
is the exact same type the btree class template is instantiated with. (e.g. for btree<Node>
, the actual signature would be ostream& operator<<(ostream &, Node);
-- assuming you hace members i
and n
of type Node
)
This function will have access to private and protected members (variables and functions) of the class btree<T>
for all instances of T
, but it is not actually a member of the class (as it would be without the friend
keyword).
The operator definition you provide is for an operator that is a member of the template class btree, as if you have declared
template<class T>
class btree
{
public:
ostream& operator<<(ostream &,T);
};
This is due to the btree<T>::
prefix you included (that specifies which class the function/operator belongs to).
Since there is no corresponding operator declaration in the class (see the above description of the friend declaration), the compiler complains.
To fix it, you either
- keep the friend declaration, remove the
btree<T>::
prefix and template<class T>
from the operator defintion and change the second parameter type to btree<Type>&
, where Type
is one of the types you expect the btree template to be instantiated with (e.g. Node
) -- then supply similar defintions for other such types as well.
- or remove the
friend
keyword from the declaration in the class and remove the T
parameter from both the declaration and the definition as now the operator is supposed to work on the whole btree (which is implicitly supplied via *this
).
- Alternatively, you can experiment with declaring the friend operator as a template, but that requires some more modifications: (read more about forward declaration)
template<class T> btree; // forward declaration of class btree
// forward declare operator (or move definition here)
template<class T>
ostream& operator<<(ostream &o, btree<T>& s);
// declare operator as template friend
template<class T>
class btree
{
public:
friend ostream& operator<< <> (ostream &, bree<T>&);
// note <> after operator name to denote template with no new template parameters
};
Note that above I assumed that you want to output the whole tree (that is invoke the operator<<
on a btree object). It is not clear from the code you have whether this is your intention (class btree does not have members i
and n
). If not, and the type you want to invoke the <<
operator on is the actual template parameter of btree, then you don't need to change the second parameter of the templated operator from T
, but there is also no need to declare it as friend
of class btree as the operator is independent of btree. You do need to declare it as friend of the class whose members i
and n
you are accessing in the definiton of the operator (e.g Node above), if i
and/or n
is private in that class. The notion about losing btree<T>::
(or Node::
) still applies as the operator does not belong to any class.
Couple more things, assuming you go with the friend declaration:
- The type of the second parameter to the operator should be
btree<T>&
(emphasis on &
) as it is more efficient to pass a reference to the btree object than to copy the entire btree (or a shallow copy if you use pointers and go with the default copy-contructor)
- the second parameter should also be marked
const
, as (presumably) you do not want to change the btree object during output. Be aware that in this case you will need to mark certain non-changing methods in btree<T>
as const
as well to allow it to compile. (See the FAQ on const correctness)
EDIT'd a few times to make it clear and ensure correctness