Overloading << operator on template classes - c++

I have made a template class for a node in a linked list and I'm trying to have it output its contents to an output stream by overloading <<. However my current code:
#include <iostream>
using namespace std;
template<class NType> class Node;
template<class NType>
class Node {
private:
void deletePointer(NType* p);
public:
NType data;
Node *prev, *next;
template<typename T>
struct is_pointer { static const bool value = false; };
template<typename T>
struct is_pointer<T*> { static const bool value = true; };
Node();
Node(NType data);
~Node();
};
int main() {
Node<int> *n1 = new Node<int>();
Node<int> *n2 = new Node<int>(10);
std::cout << "Node 1: " << n1 << std::endl;
std::cout << "Node 2: " << n2 << std::endl;
}
template<class NType> inline std::ostream & operator << (std::ostream& out, const Node<NType> &node){
out << node.data;
return out;
}
template<class NType> inline Node<NType>::Node()
:data(NULL), prev(NULL), next(NULL)
{
}
template<class NType> inline Node<NType>::Node(NType data)
:data(data), prev(NULL), next(NULL)
{
}
template<class NType> inline Node<NType>::~Node(){
if(is_pointer<NType>::value){
deletePointer(&data);
} else {
return;
}
}
template<class NType> inline void Node<NType>::deletePointer(NType* p){
delete p;
}
Outputs memory locations rather than the data within the nodes. This happens with primitive types such as int and the like as if it didn't know what kind of data was in the NType container.
Node 1: 0x741010
Node 2: 0x741030
Node 3: 0x741070
Node 4: 0x741090
I've tried using typename rather than class but still no dice... Is there any way to dynamically find out what type the template is using and cast or something prior to insertion? I know I can make a ton of redundant code for all the primitives but that seems wasteful and unnecessary.
If it helps any, I'm compiling on Arch Linux x64 with GCC v4.6.2 20111223
Edit: Since a lot of people are mentioning it. I've also tried putting the class outside as a friend and as a stand alone function neither of which work because the stream outputs address rather than the data itself regardless of where I put it. There are no private data values to be accessed so it's OK for it to not be a friend.
Edit:
Test case: http://ideone.com/a99u5
Also updated source above.
Edit:
Added the remaining portion of my code to assist Aaron in his understanding of the code.

Your code declares the operator<< as a member function, so it would actually take the this pointer as first argument and ostream as second. Instead it needs to be a free function:
template<class NType> class Node {
public:
NType data;
Node *prev, *next;
};
//Note how this is declared outside of the class body, so it is a free function instead of a memberfunction
template<class NType> inline std::ostream& operator<<(std::ostream& out, const Node<NType>& val){
out << val.data;
return out;
}
however if your operator<< needs access to private data you need to declare it as a friend function instead:
template<class NType> class Node {
public:
NType data;
Node *prev, *next;
friend std::ostream& operator<<(std::ostream& out, const Node& val){
out << val.data;
return out;
}
};
Now for your output: If your operator<< was invoked the compiler would know the type of NType and do the right thing when streaming the data member. However since your operator<< should not have worked (as written) and it seems to give you memoryaddresses as output I would assume you have something like the following:
Node* n = new Node();
std::cout<<n;
//When it should be:
std::cout<<*n;
Now just for curiosity sake: Why are you implementing what looks curiously like a linked list yourself instead of simply using std::list?
Edit:
Now that we can see the testcase it seems the assumptions about how the operator<< was called was correct. The output needs to be changed to:
std::cout << "Node 1: " << *n1 << std::endl;
std::cout << "Node 2: " << *n2 << std::endl;
to actually invoke the operator<< for Node, instead of the generic one for T*

Why are you adding a template<class NType> in front of your already templated class method?
Generally, the best way of overloading operator<< is to make it a friend:
template<typename NType>
friend std::ostream& operator<<(std::ostream& out, const Node<NType>& node)
{
out << node.data;
return out;
}
Edit: To respond to the comment below, this is what I mean:
When you define a class template in the header, you don't redeclare that template for the member functions of the class:
template<typename T>
class Foo
{
T some_data;
void member_fn();
}
This is required when you're declaring a non-member friend function, however:
template<typename NType>
class Node
{
public:
NType data;
Node<NType> *prev, *next;
//Note the different template parameter!
template<typename NType1>
friend std::ostream& operator<<(std::ostream& out, const Node<NType1>& node);
};
Implementation of that then becomes the above template<typename NType> std::ostream& operator<<(std::ostream& out, const Node<NType>& node) implementation.

template <class NType>
class Node
{
public:
NType data;
Node *prev, *next;
};
template <class NType>
inline std::ostream& operator<<(std::ostream& os, const Node<NType>& n)
{
return out << n.data;
}

You're printing the node addresses, not the nodes:
int main() {
Node<int> *n1 = new Node<int>();
Node<int> *n2 = new Node<int>(10);
std::cout << "Node 1: " << n1 << std::endl;
std::cout << "Node 2: " << n2 << std::endl;
}
n1 and n2 are pointers, not objects. You should have written:
int main() {
Node<int> *n1 = new Node<int>();
Node<int> *n2 = new Node<int>(10);
std::cout << "Node 1: " << *n1 << std::endl;
std::cout << "Node 2: " << *n2 << std::endl;
}
or:
int main() {
Node<int> n1();
Node<int> n2(10);
std::cout << "Node 1: " << n1 << std::endl;
std::cout << "Node 2: " << n2 << std::endl;
}

Others have pointed out that you need to use cout << *n1 instead of cout << n1, but there is another important bug in your code.
Your destructor includes a call deletePointer(&data); where data is a member of the class. This is dangerous. If this line of code ever was executed, then the program would probably crash. data is just one small part of the object pointed at by this, trying to delete it is like trying to delete a single element in an array is ints.
Node<int> *n1 = new Node<int>();
delete n1; // this makes sense. deleting the same thing that was new'ed
Node<int> *n1 = new Node<int>();
delete &(n1->data); // BUG
You should probably change your design a lot and simply remove the special code for pointer. Do you expect to write code like: Node<int*> *n2 = new Node<int*>( new int ); ? And if so, how do you want it to behave?
If NType actually was a pointer type, like int*, then it might make sense to do deletePointer(data), but it'll never make sense to do deletePointer(&data).

Related

Is ostream& operator<< better practice in a class than using std::cout?

In a Linked List class, I created a display method to print out the Linked List as it is currently formulated like so:
void LinkedList::display() {
Node* curr = m_head;
while (curr) {
std::cout << curr->n_data << " -> ";
curr = curr->n_next;
}
std::cout << std::endl;
}
One of the TA's who graded the assignment left a comment:
Never do cout in a class file. Use ostream& operator<< instead.
Classes shouldn't care about where you are outputting to (file/console/etc).
We hadn't yet learned about operator overloading at the time of this assignment, but I'm still not really sure.
How would I actually implement and use the ostream& operator>> to print to the console? Why is this best practice?
The simplest solution in this case would be to add a std::ostream parameter to your display() method, eg:
void LinkedList::display(std::ostream &out) const {
Node* curr = m_head;
while (curr) {
out << curr->n_data << " -> ";
curr = curr->n_next;
}
out << std::endl;
}
LinkedList list;
...
list.display(std::cout);
Then, if down the line, you decide to overload operator<<, it can simply call display(), eg:
std::ostream& operator<<(std::ostream &out, const LinkedList &list) {
list.display(out);
return out;
}
LinkedList list;
...
std::cout << list;

template using another template

Here is a cut-down version of a template List code (adapted from http://www.daniweb.com/software-development/cpp/threads/237391/c-template-linked-list-help)
List complains (compile error) that "Node is not a type". Why is this, and what is the fix?
I tried replacing the "class Node" with a "struct Node" (and related changes), and the struct version worked fine. So the main question seems to be: how does a template-class access another template-class?
#include <iostream>
using namespace std;
template <typename T>
class Node
{
public:
Node(){}
Node(T theData, Node<T>* theLink) : data(theData), link(theLink){}
Node<T>* getLink( ) const { return link; }
const T getData( ) const { return data; }
void setData(const T& theData) { data = theData; }
void setLink(Node<T>* pointer) { link = pointer; }
private:
T data;
Node<T> *link;
};
template <typename T>
class List {
public:
List() {
first = NULL;
last = NULL;
count = 0;
}
void insertFirst(const T& newData) {
first = new Node(newData, first);
++count;
}
void printList() {
Node<T> *tempt;
tempt = first;
while(tempt != NULL){
cout << tempt->getData() << " ";
tempt = tempt->getLink();
}
}
~List() { }
private:
Node<T> *first;
Node<T> *last;
int count;
};
int main() {
List<int> myIntList;
cout << "Inserting 1 in the list...\n";
myIntList.insertFirst(1);
myIntList.printList();
cout << endl;
List<double> myDoubleList;
cout << "Inserting 1.5 in the list...\n";
myDoubleList.insertFirst(1.5);
myDoubleList.printList();
cout << endl;
}
You are using
new Node(newData, first);
within the List template. At that point, Node does not refer to a type, but to a template. But of course to create an instance of a type with new, you need a type there.
The most probable thing you want to do is to make it a type by instantiating the template, i.e.
new Node<T>(newData, first);

No viable conversion from 'Template<int>::Memberclass' to 'const int'

I'm having a problem with return value/reference. I'm writing a template (queue), and Front() function is supposed to return the element from the front of the queue, but I get an error -- No viable conversion from 'Queue<int>::Node' to 'const int'. When I remove const, I get Non-const lvalue reference to type 'int' cannot bind to a value of unrelated type 'Queue<int>::Node' instead, and other variations of reference/no reference, const/no const give me either of the two errors. What am I missing?
#include <iostream>
using namespace std;
template <typename T>
class Queue
{
friend ostream& operator<< (ostream &, const Queue<T> & );
private:
class Node
{
friend class Queue<T>;
public:
Node(const T &t): node(t) {next = 0;}
private:
T front;
T back;
T node;
Node *next;
};
Node *front;
Node *back;
public:
Queue() : front(0), back(0) {}
~Queue();
bool Empty()
{
return front == 0;
}
T& Front()
{
if (Empty())
cout << "Очередь пуста." << endl;
else
{
T const & temp = *front; // error here
return temp;
}
}
/* ... */
};
template <class T> ostream& operator<< (ostream &, const Queue<T> & );
int main()
{
Queue<int> *queueInt = new Queue<int>;
for (int i = 0; i<10; i++)
{
queueInt->Push(i);
cout << "Pushed " << i << endl;
}
if (!queueInt->Empty())
{
queueInt->Pop();
cout << "Pop" << endl;
}
queueInt->Front();
return 0;
}
Your Node class definition doesn't make much sense: the way it's now, each node stores 3 data values: front, back and node. Is the class supposed to be a queue of triples?
Nevertheless, in your Front() function, you to need to return the "payload" of the front node (i.e. return something of type T), not the node itself. Something like this:
T& Front()
{
if (Empty())
cout << "Очередь пуста." << endl;
else
{
return front->node;
}
}
Replace
T const & temp = *front;
with
T& temp = front->front;
Queue<T>::front is a pointer to a Node, in other words, *front is a Node. You are trying then to assign a Node to a T& const and, since the compiler cannot convert from Node to T it complains. Now, the Node has a member also called front which is T and I suppose that's what you want to return and that's what the fix does. (Possibly you want to return front->node. Your intent is not clear to me.)
In addition, you declared temp as T const & and Front returns it. However, the type returned by Front is T& (non nonst) and the compiler cannot convert from const to non-const. By declaring temp non-const (as in the fix) such conversion is no longer required.

c++ class template return value error

I was using eclipse to code up a queue, one function called getFirst is defined as:
template<class T>
T getFirst(){
return head->data;
}
in the main, after declaring the queue Q and input some valid data like:
Queue<int> Q;
Q.add(2);
cout << Q.getFirst() << endl;
The output is 2, which is just what I desired;
But!!! If I change the code to:
Queue<int> Q;
Q.add(2);
cout << Q.getFirst() << endl;
cout << Q.getFirst() << endl;
the output is not:
2
2
but something like:
2
2657382
after a few thoughts, I modified the code to:
Queue<int> Q;
Q.add(2);
cout << Q.getFirst();
cout << Q.getFirst() << endl;
this time it worked!! Just fine!! the output is 22, which make sense.
Can anybody kindly explain to me the problem here?
The definition of Node and Queue is generic and general :
template<typename T>
class Node{
public:
Node(T data, Node* left = 0, Node* right = 0): _data(data), _left(left), _right(right){
if(left)
left->_right = this;
if(right)
right->_left = this;
}
Node(): _right(0){}
private:
T _data;
Node<T>* _left;
Node<T>* _right;
friend class Queque<T>;
};
template<typename T>
class Queque{
public:
Queque(): _first(new Node<T>), _size(0){
_first->_right = _first;
_first->_left = _first;
}
void addFirst(T item){
Node<T>(item, _first, _first->_right);
_size++;
}
T examineFirst(){
return _first->_right->_data;
}
private:
Node<T>* const _first;
int _size;
};
void addFirst(T item){
Node<T>(item, _first, _first->_right);
_size++;
}
Node is a stack variable, and it's constructor will change _first, and first->_right to be pointing to some stack address, which will lead for unpredicted results, in your example usage << endl; modified stack, leading to some garbage output. To fix this you need to use new for new nodes allocation and, of course free them later with delete.

I have an error on my stack using a linked list. Unable to print loop of numbers. (C++)

$ I have the following error:
44 E:\Assignment 2.cpp no match for 'operator<<' in 'std::cout < (&number)->newstack::push(x)'
$ I'm using a linked list to put numbers in a class stack that contains a struct. The stack that contains these numbers are printed out. But the error will not allow me to print them out.
#include <iostream>
using namespace std;
typedef int itemType;
class newstack
{
private:
Using a struct of nodes which contains a item and pointer to the next node.
struct node
{
itemType item;
node *next;
};
node *top; //pointer to the top node.
public:
void push(itemType newItem); //adds items to newstack
};
int main()
{
newstack number;
int x;
cout<< "Number Stack" <<endl;
for (x=0;x<=9;x++)
cout<<(number).push(x)<<endl; //ERROR LINE
//Takes 9 integers and adds them to the stack by printing them out.
return 0;
}
void newstack::push(itemType newItem)
// Precondition: Stack is empty.
//Postcondition: Stack contains a itemType at the top and list or stack implements by 1.
{
if(top!=NULL)
node *newTop;
newTop=new node;
(*newTop).item=newItem;
(*newTop).next=top;
top=newTop;
}
IN your push() function you are returning Void.
Yet you try and write the value the function returns
to the command prompt - either change your push function
to return a value or cout << stack.pop();
Further On:
You need to overload the << operator for your newstack class to be able to write something like:
newstack obj;
cout<<obj;
<< is overloaded for only built-in data types not custom class types.
You need to overload it something like this:
std::ostream& operator<<(std::ostream& os, const newstack& obj);
cout<<(number).push(x)<<endl;
First, you don't need the () around number
cout << number.push(x) << endl;
That still won't work, because newstack::push returns void.
Either change newstack::push to return the value added, or print the number in a separate step.
See The Following
#include <iostream>
using namespace std;
//Defenitions
template <class T>
struct Node
{
T DataMember;
Node* Next;
};
template <class T>
class NCA
{
public:
NCA();
~NCA();
void push(T);
T pop();
void print();
void Clear();
private:
Node<T>* Head;
void* operator new(unsigned int);
};
//Imp.
template <class T>
NCA<T>::NCA()
{
Head = NULL;
}
template <class T>
NCA<T>::~NCA()
{
Clear();
}
template <class T>
void NCA<T>::push(T value)
{
Node<T>* Temp = new Node<T>;
Temp->DataMember = value;
Temp->Next = Head;
Head = Temp;
}
template <class T>
T NCA<T>::pop()
{
Node<T>* n;
T i;
n = Head->Next;
i = Head->DataMember;
delete Head;
Head = n;
return i;
}
template <class T>
void NCA<T>::print()
{
Node<T>* MockHead = Head;
while (MockHead != NULL)
{
cout << MockHead->DataMember;
MockHead = MockHead->Next;
}
}
template <class T>
void NCA<T>::Clear()
{
while(Head != NULL)
pop();
}
//Main Execution
int main()
{
NCA<char> Array;
Array.push('c');
cout << Array.pop();
return 0;
}
You haven't override the operator << for your newstack which is causing the error. If you printed x, then did the push afterwards, you wouldn't receive an error. If you want cout to be able to print your stack you need to define HOW the << operator works.
The real problem here is how you're expecting your code to work. First, push shouldn't return a value to begin with, that's not how a stack works. You could implement pop which would pop off and return the top value of the stack, however then you're losing that value. You need to implement peek. Because this is homework I wont give you a direct answer on how to write peek but this should be a better way of executing your code.
for (x=0; x<=9; x++)
{
number.push(x);
cout << number.peek() << endl;
}