I'm implementing a dictionary in C++ using a binary tree, each node in my tree has a key(int
), item(string
) and left and right child.
During this implementation, I overloaded the ostream operator for my BinaryTree
class to print out the contents of the tree.
Additionally, I overloaded the ostream to work with Node
pointers that would then print out the key and the item of that node.
This worked fine. However when I tried to then make the tree a template to work with any type for my key or item overloading these operators became more difficult.
I isolated the problem to make it easier to work on, additionally, I have tried playing around with both a node and a node pointer to see if I can get one to work without the other.
Here is the class I have made to test the problem, this class is not templated and works fine.
test.h
class myClass
{
public:
using Key = int;
myClass(Key);
friend std::ostream & operator<<(std::ostream &, const myClass &);
private:
struct Thing {
Key data;
Thing();
Thing(Key);
};
Thing* B;
Thing A;
void disp(std::ostream &) const;
friend std::ostream & operator<<(std::ostream &, myClass::Thing);
friend std::ostream & operator<<(std::ostream &, myClass::Thing *);
};
test.cpp
myClass::Thing::Thing(Key Num) { data = Num; }
myClass::myClass(Key Num)
{
A = Thing(Num); B = &A;
}
void myClass::disp(std::ostream & os) const
{
os << A << std::endl; os << B << std::endl;
}
std::ostream & operator<<(std::ostream & os, const myClass & c)
{
c.disp(os); return os;
}
std::ostream & operator<<(std::ostream & os, myClass::Thing th)
{
os << th.data; return os;
}
std::ostream & operator<<(std::ostream & os, myClass::Thing *th)
{
os << th->data; return os;
}
With this class, I can easily make an instance of my class and std::cout
it giving the output as expected.
Then turning this class into a template:
template <class T> class myTemplate
{
public:
using Key = T;
myTemplate(Key);
template<class A>
friend std::ostream & operator<<(std::ostream &, const myTemplate<A> &);
private:
struct Thing;
Thing A;
Thing* B;
void disp(std::ostream &) const;
template <class A> friend std::ostream & operator<<(std::ostream &, typename myTemplate<A>::Thing);
template <class A> friend std::ostream & operator<<(std::ostream &, typename myTemplate<A>::Thing *);
};
template <class T> struct myTemplate<T>::Thing
{
T data;
Thing() = default;
Thing(Key);
};
//Create new thing A with B a pointer to A
template <class T> myTemplate<T>::myTemplate(Key Num)
{
A = Thing(Num);
B = &A;
}
//Displays Node A & B
template <class T> void myTemplate<T>::disp(std::ostream & os) const
{
os << A << std::endl; os << B << std::endl;
}
template <class T> myTemplate<T>::Thing::Thing(Key Num)
{
data = Num;
}
//Overloading << will call disp function, in turn print A & B to stream
template<class T> std::ostream & operator<<(std::ostream & os, const myTemplate<T> & c)
{
c.disp(os); return os;
}
//Output a to stream
template <class A> std::ostream & operator<<(std::ostream & os, typename myTemplate<A>::Thing th)
{
os << th.data; return os;
}
//Output a to stream
template <class A> std::ostream & operator<<(std::ostream & os, typename myTemplate<A>::Thing *th)
{
os << th->data; return os;
}
However with myTemplate
when I tried in the main()
:
myTemplate Template(5);
cout << Template;
The code will not compile as I get the error:
Error C2679 binary '<<': no operator found which takes a right-hand operand of type 'const myTemplate<std::string>::Thing' (or there is no acceptable conversion)
Additionally commenting out the line:
os << A << std::endl;
So only B
is being outputted to the stream, the code will compile. However the data of B
is not outputted, only the memory address of B
.
I have noticed that using breakpoints when trying to output B
the code does not even use the overload function I defined. This is not the case for the non-templated class as the overloads I defined are used for both A
and B
.
So what is the correct way to overload the ostream operator to work for the struct member?
Apologises for the long winded question, felt I should include what I had determined myself.