I've tried to make a class List, with iterator:
#ifndef UTIL_H
#define UTIL_H
#include <iostream>
#include <exception>
namespace Util
{
class IndexOutOfBounds : public std::exception
{
virtual const char* what()
{
return "Index out of bounds";
}
};
template<class T>
class Iterator;
template <class T>
class ListNode
{
template<class R>
friend class Iterator;
template<class R>
friend class List;
public:
ListNode()
{
init();
}
ListNode(T info)
{
init();
this->info=info;
}
static void link(ListNode<T> first, ListNode<T> second)
{
first.next=&second;
second.prev=&first;
}
template<class R>
friend std::ostream& operator<< (std::ostream& out, const ListNode<R>& node);
template<class R>
friend std::istream& operator>> (std::istream& in, const ListNode<R>& node);
private:
T info;
ListNode<T>* next;
ListNode<T>* prev;
void init()
{
next=prev=this;
}
};
template<class T>
std::ostream& operator<< (std::ostream& out , const ListNode<T>& node)
{
out << node.info;
return out;
}
template<class T>
std::istream& operator>> (std::istream& in , const ListNode<T>& node)
{
in >> node.info;
return in;
}
template <class T>
class List
{
friend class ListNode<T>;
template <class R>
friend class Iterator;
private:
unsigned int length;
ListNode<T>* node;
public:
List()
{
node=new ListNode<T>();
length=0;
}
unsigned int size() const
{
return length;
}
void insert(int i,T info) throw()
{
ListNode<T>* ptr=node,*next_ptr;
try
{
if(i>(int)length || i<0)
throw IndexOutOfBounds();
for(int j=0;j<i;j++)
ptr=ptr->next;
next_ptr=ptr->next;
ptr->next=new ListNode<T>(info);
ptr->next->prev=ptr;
ListNode<T>::link(*(ptr->next),*next_ptr);
length++;
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void push_back(T info) throw()
{
try
{
insert(length,info);
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void push_front(T info) throw()
{
try
{
insert(0,info);
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void remove(int i) throw()
{
ListNode<T>* ptr=node,*next_ptr;
try
{
if(i>=length || i<0)
throw IndexOutOfBounds();
for(int j=0;j<i;j++)
ptr=ptr->next;
next_ptr=ptr->next->next;
delete ptr->next;
ListNode<T>::link(*ptr,*next_ptr);
length--;
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void pop_back() throw()
{
try
{
remove(length-1);
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void pop_front() throw()
{
try
{
remove(0);
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
Iterator<T> begin()
{
Iterator<T> result;
result.ptr=node->next;
return result;
}
Iterator<T> last()
{
Iterator<T> result;
result.ptr=node->prev;
return result;
}
Iterator<T> end()
{
Iterator<T> result;
result.ptr=node;
return result;
}
template <class R>
friend std::ostream& operator<< (std::ostream& out , const List<R>& l);
template <class R>
friend std::istream& operator>> (std::istream& in , const List<R>& l);
typedef Iterator<T> iterator;
};
template<class T>
std::ostream& operator<< (std::ostream& out , const List<T>& l)
{
Iterator<T> i=l.begin();
return out;
}
template<class T>
std::istream& operator>> (std::istream& in , const List<T>& l)
{
for(Iterator<T> i=l.begin();i!=l.end();i++)
in >> *i;
return in;
}
template <class T>
class Iterator
{
friend class List<T>;
friend class ListNode<T>;
private:
ListNode<T>* ptr;
public:
Iterator()
{
ptr=NULL;
}
Iterator(const Iterator<T>& i)
{
ptr=i.ptr;
}
Iterator<T>& operator= (Iterator<T> i)
{
ptr=i.ptr;
return *this;
}
Iterator<T>& operator++ ()
{
ptr=ptr->next;
return *this;
}
Iterator<T> operator++ (int)
{
Iterator<T> i=*this;
++*this;
return i;
}
Iterator<T>& operator-- ()
{
ptr=ptr->prev;
return *this;
}
Iterator<T> operator-- (int)
{
Iterator<T> i=*this;
--*this;
return i;
}
T& operator* ()
{
return ptr->info;
}
template<class R>
friend bool operator!= (Iterator<R>& i, Iterator<R>& j);
template<class R>
friend bool operator== (Iterator<R>& i, Iterator<R>& j);
};
template <class T>
bool operator!= (Iterator<T>& i, Iterator<T>& j)
{
return i.ptr!=j.ptr;
}
template <class T>
bool operator== (Iterator<T>& i, Iterator<T>& j)
{
return i.ptr==j.ptr;
}
}
#endif
But I get these errors:
/home/ramy/Documents/C++/Prova/Util.h||In function ‘std::ostream& Util::operator<<(std::ostream&, const Util::List<T>&) [with T = int]’:|
/home/ramy/Documents/C++/Prova/main.cpp|11|instantiated from here|
/home/ramy/Documents/C++/Prova/Util.h|218|error: passing ‘const Util::List<int>’ as ‘this’ argument of ‘Util::Iterator<T> Util::List<T>::begin() [with T = int]’ discards qualifiers|
||=== Build finished: 1 errors, 0 warnings ===|
With this main:
#include <iostream>
#include "Util.h"
using namespace Util;
int main(int argc, char** argv)
{
List<int> l;
for(int i=0;i<10;i++)
l.push_back(i);
std::cout << l;
return 0;
}
I don't why I get this error, it seems like the operator = is not considered right.
It sounds absurd to me, but of course there will be an explanation.
you need a
ConstIterator<T> List<T>::begin() const;
// ^^^^^
With a corresponding ConstIterator type so that the list in Util::operator<< can actually iterate over that list. non-const member functions cannot be used on const references, even if the referent is itself non-const.
While you're at it, you should probably define a pile of other const member functions for List<T>
Looks like you're calling non-const method (begin()) on a const object.
Related
Here is a first attempt at iterator of a doubly linked list:
dlist.h
#ifndef dlist_h
#define dlist_h
/* Node */
template <class Elem>
struct Link
{
Link();
Link (Link<Elem>* s, Link<Elem>* p, const Elem& v);
Link (const Link<Elem>& src);
Link<Elem>& operator= (const Link<Elem>& src);
bool operator== (const Link<Elem>& src);
bool operator!= (const Link<Elem>& src);
void swap(Link<Elem>& src);
Link* succ;
Link* prev;
Elem val;
};
//----------------------------------------------------------------------------
/* Doubly Linked List */
template <class Elem>
class List
{
public:
class iterator;
List();
iterator begin() { return iterator(first, first, last); }
iterator end() { return iterator(last, first, last); }
void push_front(const Elem& v);
Elem& front();
size_t size();
void print();
private:
Link<Elem> *first;
Link<Elem> *last;
};
//----------------------------------------------------------------------------
/* a range-checked bidirectional iterator */
template <class Elem>
class List<Elem>::iterator
{
public:
iterator(); // default constructor
iterator(Link<Elem>* c, Link<Elem>* b, Link<Elem>* e);
iterator(const iterator& src); // copy constructor
iterator operator= (const iterator& src); // copy assignment
iterator& operator++(); // incrementations
iterator operator++(int); // postfix
iterator& operator--(); // decrementations
iterator operator--(int); // postfix
Elem& operator*(); // dereferenceable lvalue
const Elem& operator*() const; // dereferenceable rvalue
bool operator== (const iterator& b) const; // equality comparisons
bool operator!= (const iterator& b) const;
void swap(iterator& src);
private:
Link<Elem>* curr;
Link<Elem>* begin;
Link<Elem>* end;
};
#include "dlist.cpp"
#endif
dlist.cpp
//-----------------------------------------------------------------------------
template <class Elem>
Link<Elem>::Link()
: succ(nullptr), prev(nullptr), val(Elem())
{
}
//-----------------------------------------------------------------------------
template <class Elem>
Link<Elem>::Link (Link<Elem>* s, Link<Elem>* p, const Elem& v)
: succ(s), prev(p), val(v)
{
}
//-----------------------------------------------------------------------------
template <class Elem>
Link<Elem>::Link (const Link<Elem>& src)
: succ(src.succ), prev(src.prev), val(src.val)
{
}
//-----------------------------------------------------------------------------
template <class Elem>
Link<Elem>& Link<Elem>::operator= (const Link<Elem>& src)
{
Link<Elem> temp(src);
swap(*this, temp);
return *this;
}
//-----------------------------------------------------------------------------
template <class Elem>
bool Link<Elem>::operator== (const Link<Elem>& src)
{
return succ = src.succ && prev = src.prev;
}
//-----------------------------------------------------------------------------
template <class Elem>
bool Link<Elem>::operator!= (const Link<Elem>& src)
{
return !(*this == src);
}
//-----------------------------------------------------------------------------
template <class Elem>
void Link<Elem>::swap(Link<Elem>& src)
{
std::swap(prev, src.prev);
std::swap(succ, src.succ);
std::swap(val, src.val);
}
//-----------------------------------------------------------------------------
template<class Elem>
void swap(Link<Elem>& lhs, Link<Elem>& rhs)
{
lhs.swap(rhs);
}
//-----------------------------------------------------------------------------
template<class Elem>
List<Elem>::List()
: first(new Link<Elem>()), last(first)
{
}
//-----------------------------------------------------------------------------
template<class Elem>
void List<Elem>::push_front(const Elem& v)
{
first = new Link<Elem>(first, nullptr, v);
}
//-----------------------------------------------------------------------------
template<class Elem>
Elem& List<Elem>::front()
{
return first->val;
}
//-----------------------------------------------------------------------------
template<class Elem>
size_t List<Elem>::size()
{
size_t count = 0;
for (iterator p = begin(); p != end(); ++p)
{
++count;
}
return count;
}
//-----------------------------------------------------------------------------
template<class Elem>
void List<Elem>::print()
{
for (iterator p = begin(); p != end(); ++p)
{
std::cout << *p <<' ';
}
}
//-----------------------------------------------------------------------------
template<class Elem>
List<Elem>::iterator::iterator()
: curr(nullptr), begin(nullptr), end(nullptr)
{
}
//-----------------------------------------------------------------------------
template<class Elem>
List<Elem>::iterator::iterator(Link<Elem>* p, Link<Elem>* b, Link<Elem>* e)
: curr(p), begin(b), end(e)
{
}
//-----------------------------------------------------------------------------
template<class Elem>
List<Elem>::iterator::iterator(const iterator& src)
: curr(src.curr), begin(src.begin), end(src.end)
{
}
//-----------------------------------------------------------------------------
template<class Elem>
typename List<Elem>::iterator List<Elem>::iterator::operator= (const iterator& src)
{
iterator temp(src);
this->swap(temp);
return *this;
}
//-----------------------------------------------------------------------------
template<class Elem>
typename List<Elem>::iterator& List<Elem>::iterator::operator++()
{
if (curr == end)
{
throw std::out_of_range("List<Elem>::iterator::operator++(): out of range!\n");
}
curr = curr->succ;
return *this;
}
//-----------------------------------------------------------------------------
template<class Elem>
typename List<Elem>::iterator List<Elem>::iterator::operator++(int)
{
if (curr == end)
{
throw std::out_of_range("List<Elem>::iterator::operator++(): out of range!\n");
}
Link<Elem>* old = curr;
curr = curr->succ;
return old;
}
//-----------------------------------------------------------------------------
template<class Elem>
typename List<Elem>::iterator& List<Elem>::iterator::operator--()
{
if (curr == begin)
{
throw std::out_of_range("List<Elem>::iterator::operator--(): out of range!\n");
}
curr = curr->prev;
return *this;
}
//-----------------------------------------------------------------------------
template<class Elem>
typename List<Elem>::iterator List<Elem>::iterator::operator--(int)
{
if (curr == begin)
{
throw std::out_of_range("List<Elem>::iterator::operator--(): out of range!\n");
}
iterator old(*this);
curr = curr->prev;
return old;
}
//-----------------------------------------------------------------------------
template<class Elem>
Elem& List<Elem>::iterator::operator*()
{
return curr->val;
}
//-----------------------------------------------------------------------------
template<class Elem>
const Elem& List<Elem>::iterator::operator*() const
{
return curr->val;
}
//-----------------------------------------------------------------------------
template<class Elem>
bool List<Elem>::iterator::operator== (const iterator& b) const
{
return curr == b.curr;
}
//-----------------------------------------------------------------------------
template<class Elem>
bool List<Elem>::iterator::operator!= (const iterator& b) const
{
return curr != b.curr;
}
//-----------------------------------------------------------------------------
template<class Elem>
void List<Elem>::iterator::swap(iterator& src)
{
std::swap(curr, src.curr);
std::swap(begin, src.begin);
std::swap(end, src.end);
}
//-----------------------------------------------------------------------------
template<class Elem>
void swap(typename List<Elem>::iterator& lhs, typename List<Elem>::iterator& rhs)
{
lhs.swap(rhs);
}
main.cpp
#include <iostream>
#include "dlist.h"
/* simple test for iterator */
int main()
{
List<int> l;
l.push_front(1);
l.push_front(2);
l.push_front(3);
l.push_front(4);
l.push_front(5);
// default constructor, copy assignment
List<int>::iterator p = l.begin();
// lvalue dereferencing
*p = 100;
// incrementation, rvalue dereferencing
List<int>::iterator i;
for (i = l.begin(); i != l.end(); ++i)
{
std::cout << *i <<' ';
}
if (i == l.end() && i != l.begin())
{
std::cout <<"\ncomparison correct!\n";
}
// postfix and prefix decrementation; maintain dereferenceability
List<int>::iterator ii = l.end();
--ii;
for (; ii != l.begin(); ii--)
{
std::cout << *ii <<' ';
}
return 0;
}
When it reaches the last for loop the decrement operator-- somehow invalidates the ii iterator and I can't figure it out despite a thoroughIMO debugging.
Here is a runnable sample.
The problem is your push_front method, you forgot to link first->succ->prev back to new node, hence your doubly linked list is basically a singly linked list
The first i-- succeed because last points to a default node, but curr->prev is a nullptr since you forgot to link back, so the next i-- will deref the nullptr curr cause the error.
Fix your push_front method:
template<class Elem>
void List<Elem>::push_front(const Elem& v)
{
first = new Link<Elem>(first, nullptr, v);
first->succ->prev = first; //link back
}
Your constructor for Link does not properly update the elements given as arguments. Inserting an element between two elements breaks the previous link.
This is a more appropriate constructor :
template <class Elem>
Link<Elem>::Link(Link<Elem>* s, const Elem& v)
: succ(s), prev(s->prev), val(v)
{
// Update next and previous nodes to make them aware of this
s->prev = this;
if(prev) prev->succ = this;
}
If you update List::push_front to use this constructor instead, you will find that your code compiles and runs.
You should consider making methods const when appropriate to avoid mistakes (or to spot existing onw them in the case of bool operator== (const Link<Elem>& src) const). Link.
I'm working on a file, Deque.hpp, which uses an iterator class and Nodes to make a deque, but I'm getting the error:
"Error C1004 unexpected end-of-file found "
I can't seem to find what's causing this. Here's my code.
#ifndef DEQUE_H
#define DEQUE_H
#include <iostream>
#include <new>
#include <cstdlib>
#include <algorithm>
//
//
//
template <typename T>
class Deque
{
public:
Deque();
Deque(const Deque & rhs);
~Deque();
Deque & operator= (const Deque & rhs);
Deque(Deque && rhs) : theSize{ rhs.theSize }, head{ rhs.head }, tail{ rhs.tail };
Deque & operator= (Deque && rhs);
T & Deque<T>::operator[](int n);
Iterator begin();
const_iterator begin() const;
Iterator end();
const_iterator end() const;
int size() const;
bool isEmpty() const;
void clear();
T & left();
const T & left() const;
T & right();
const T & right() const;
void pushLeft(const T & x);
void pushLeft(T && x);
void pushRight(const T & x);
void pushRight(T && x);
T & popLeft();
T & popRight();
bool Deque<T>::contains(const T&);
struct Node
{
T data;
Node *prev;
Node *next;
Node(const T & d = T{}, Node * p = NULL, Node * n = NULL) :
data{ d }, prev{ p }, next{ n } {}
Node(T && d, Node * p = NULL, Node * n = NULL)
: data{ std::move(d) }, prev{ p }, next{ n } {}
};
class const_iterator
{
public:
const_iterator() : current{ NULL } { }
const T & operator* () const;
const_iterator & operator++ ();
const_iterator & operator-- (); //!
const_iterator operator++ (int);
const_iterator operator-- (int); //!
bool operator== (const const_iterator & rhs) const;
bool operator!= (const const_iterator & rhs) const;
protected:
Node *current;
T & retrieve() const;
const_iterator(Node *p) : current{ p } { }
friend class Deque<T>;
};
class Iterator : public const_iterator
{
public:
Iterator();
T & operator* ();
const T & operator* () const;
Iterator & operator++ ();
Iterator & operator-- (); //!
Iterator operator++ (int);
Iterator operator-- (int); //!
protected:
Iterator(Node *p) : const_iterator{ p } { }
friend class Deque<T>;
};
private:
// Insert x before itr.
Iterator insert(Iterator itr, const T & x);
// Insert x before itr.
Iterator insert(Iterator itr, T && x);
// Erase item at itr.
Iterator erase(Iterator itr);
Iterator erase(Iterator from, Iterator to);
int theSize;
Node *head;
Node *tail;
void init();
};
template<typename T>
inline const T & Deque<T>::const_iterator::operator*() const
{
return retrieve();
}
template<typename T>
inline const_iterator & Deque<T>::const_iterator::operator++()
{
current = current->next;
return *this;
}
template<typename T>
inline const_iterator & Deque<T>::const_iterator::operator--()
{
current = current->prev;
return *this;
}
template<typename T>
inline const_iterator Deque<T>::const_iterator::operator++(int)
{
const_iterator old = *this;
++(*this);
return old;
}
template<typename T>
inline const_iterator Deque<T>::const_iterator::operator--(int)
{
const_iterator old = *this;
--(*this);
return old;
}
template<typename T>
inline bool Deque<T>::const_iterator::operator==(const const_iterator & rhs) const
{
return current == rhs.current;
}
template<typename T>
inline bool Deque<T>::const_iterator::operator!=(const const_iterator & rhs) const
{
return !(*this == rhs);
}
template<typename T>
inline T & Deque<T>::const_iterator::retrieve() const
{
return current->data;
}
template<typename T>
inline Deque<T>::Iterator::Iterator()
{
}
template<typename T>
inline T & Deque<T>::Iterator::operator*()
{
return const_iterator::retrieve();
}
template<typename T>
inline const T & Deque<T>::Iterator::operator*() const
{
return const_iterator::operator*();
}
template<typename T>
inline Iterator & Deque<T>::Iterator::operator++()
{
this->current = this->current->next;
return *this;
}
template<typename T>
inline Iterator & Deque<T>::Iterator::operator--()
{
this->current = this->current->prev;
return *this;
}
template<typename T>
inline Iterator Deque<T>::Iterator::operator++(int)
{
Iterator old = *this;
++(*this);
return old;
}
template<typename T>
inline Iterator Deque<T>::Iterator::operator--(int)
{
Iterator old = *this;
--(*this);
return old;
}
template<typename T>
inline Deque<T>::Deque()
{
init();
}
template<typename T>
inline Deque<T>::~Deque()
{
clear();
delete head;
delete tail;
}
template<typename T>
inline Deque & Deque<T>::operator=(const Deque & rhs)
{
if (this == &rhs)
return *this;
clear();
for (const_iterator itr = rhs.begin(); itr != rhs.end(); ++itr)
pushRight(*itr)
return *this;
}
template<typename T>
inline Deque<T>::Deque(Deque && rhs)
{
rhs.theSize = 0;
rhs.head = NULL;
rhs.tail = NULL;
}
template<typename T>
inline Deque & Deque<T>::operator=(Deque && rhs)
{
std::swap(theSize, rhs.theSize);
std::swap(head, rhs.head);
std::swap(tail, rhs.tail);
return *this;
}
template<typename T>
inline T & Deque<T>::operator[](int n)
{
Iterator itr = begin();
for (int i = 0; i < n; i++)
{
itr.current = itr.current->next;
}
return itr.current->data;
}
template<typename T>
inline Iterator Deque<T>::begin()
{
return{ head->next };
}
template<typename T>
inline const_iterator Deque<T>::begin() const
{
return{ head->next };
}
template<typename T>
inline Iterator Deque<T>::end()
{
return{ tail->prev }; //changed to -> prev
}
template<typename T>
inline const_iterator Deque<T>::end() const
{
return{ tail->prev };
}
template<typename T>
inline int Deque<T>::size() const
{
return theSize;
}
template<typename T>
inline bool Deque<T>::isEmpty() const
{
return size() == 0;
}
template<typename T>
inline void Deque<T>::clear()
{
while (!isEmpty())
popLeft();
}
template<typename T>
inline T & Deque<T>::left()
{
return *begin();
}
template<typename T>
inline const T & Deque<T>::left() const
{
return *begin();
}
template<typename T>
inline T & Deque<T>::right()
{
return *end(); // deleted "--*end"
}
template<typename T>
inline const T & Deque<T>::right() const
{
return *end();
}
template<typename T>
inline void Deque<T>::pushLeft(const T & x)
{
insert(begin(), x);
}
template<typename T>
inline void Deque<T>::pushLeft(T && x)
{
insert(begin(), std::move(x)); // changed std::move(x)) to x
}
template<typename T>
inline void Deque<T>::pushRight(const T & x)
{
insert(end(), x);
}
template<typename T>
inline void Deque<T>::pushRight(T && x)
{
insert(end(), std::move(x));
}
template<typename T>
inline T & Deque<T>::popLeft()
{
return *begin(); erase(begin());
}
template<typename T>
inline T & Deque<T>::popRight()
{
return *end(); erase(end()); // changed --end to end
}
template<typename T>
inline bool Deque<T>::contains(const T &)
{
// stuff here
}
template<typename T>
inline Iterator Deque<T>::insert(Iterator itr, const T & x)
{
Node *p = itr.current;
theSize++;
return{ p->prev = p->prev->next = new Node{ x, p->prev, p } };
}
template<typename T>
inline Iterator Deque<T>::insert(Iterator itr, T && x)
{
Node *p = itr.current;
theSize++;
return{ p->prev = p->prev->next = new Node{ std::move(x), p->prev, p } };
}
template<typename T>
inline Iterator Deque<T>::erase(Iterator itr)
{
Node *p = itr.current;
Iterator retVal{ p->next };
p->prev->next = p->next;
p->next->prev = p->prev;
delete p;
theSize--;
return retVal;
}
template<typename T>
inline Iterator Deque<T>::erase(Iterator from, Iterator to)
{
for (Iterator itr = from; itr != to; )
itr = erase(itr);
return to;
}
template<typename T>
inline void Deque<T>::init()
{
theSize = 0;
head = new Node;
tail = new Node;
head->next = tail;
tail->prev = head;
}
template<typename T>
inline Deque<T>::Deque(const Deque & rhs)
{
init();
*this = rhs;
}
#endif
The first error to fix is the one identified by Algirdas Preidžius: your constructor has an initialization list but no body.
You should replace
Deque(Deque && rhs) : theSize{ rhs.theSize }, head{ rhs.head }, tail{ rhs.tail };
by
Deque(Deque && rhs) : theSize{ rhs.theSize }, head{ rhs.head }, tail{ rhs.tail } {};
Then you'll have a lot of other errors to fix. Good luck !
My advice when coding: write your code incrementaly, build and test regularly. You shouldn't have so much errors to fix at once !
By the way, any reason to not use std::deque ?
I'm having a problem. I have the template and implementation for a stack in files stack.h and stack.hpp. Then I have an in2out.cpp file that converts infix expressions to outfix expressions and evaluates them. At the beginning of in2out.cpp I "#include stack.h". And inside stack.h (which is my interface) I "#include stack.hpp" (stack.hpp is my implementation). I know this is weird but it's the way I'm required to do it.
Anyways, my problem is, when I'm trying to compile these 3 files together. I get only 1 error which is in stack.h (my interface, listed below). The error is:
In file included from in2post.cpp:7:
stack.h:49: error: expected declaration before â}â token
Line 49 is near the bottom. here is my stack.h file.
#ifndef STACK_H
#define STACK_H
#include <iostream>
#include <vector>
namespace cop4530 {
template<typename T>
class Stack {
private:
std::vector<T> v;
public:
Stack();
~Stack();
Stack (const Stack<T>&);
//Stack (Stack<T>&& );
Stack<T>& operator= (const Stack <T>&);
//Stack<T> & operator=(Stack<T> &&);
bool empty() const;
void clear();
void push(const T& x);
//void push(T && x);
void pop();
T& top();
const T& top() const;
int size() const;
void print(std::ostream& os, char ofc = ' ') const;
};
template<typename T>
std::ostream& operator<< (std::ostream& os, const Stack<T>& a);
template<typename T>
bool operator== (const Stack<T>& a, const Stack <T>& b);
template<typename T>
bool operator!= (const Stack<T>& a, const Stack <T>& b);
template<typename T>
bool operator< (const Stack<T>& a, const Stack <T>& b);
#include "stack.hpp"
} //this is line 49
#endif
Here's my makefile:
CC = g++
FLAGS = -Wall -pedantic
DDD = -g
in2post.x: in2post.cpp stack.h stack.hpp
$(CC) $(FLAGS) $(DDD) -o in2post.x in2post.cpp
EDIT: Here's the beginning of Stack.hpp: (tell me if I should change or add something)
EDIT2: I just decided to include the whole Stack.hpp. Some functions are blanked out cause I didn't need them or couldn't figure them out
#include <iostream>
#include <vector>
template<typename T>
Stack<T>::Stack(){}
template<typename T>
Stack<T>::~Stack(){
v.clear();
}
template<typename T>
Stack<T>::Stack(const Stack<T> & S){
v = S.v;
}
/*
template<typename T>
Stack<T>::Stack(Stack<T> &&){
}
*/
template<typename T>
Stack<T> & Stack<T>::operator=(const Stack<T> & S){
v = S.v;
return *this;
}
/*
template<typename T>
Stack<T>::Stack<T> & Stack<T>::operator=(Stack<T> &&){
}
*/
template<typename T>
bool Stack<T>::empty() const {
return v.empty();
}
template<typename T>
void Stack<T>::clear(){
while (!v.empty())
v.clear();
}
template<typename T>
void Stack<T>::push(const T& x){
v.push_back(x);
}
/*
template<typename T>
void Stack<T>::push(T && x){
}
*/
template<typename T>
void Stack<T>::pop(){
v.pop_back();
}
template<typename T>
T& Stack<T>::top(){
return v[v.size()-1];
}
template<typename T>
const T & Stack<T>::top() const{
return v[0];
}
template<typename T>
int Stack<T>::size() const {
return v.size();
}
template<typename T>
void Stack<T>::print(std::ostream & os, char ofc) const {
for(int i = 0; i < v.size(); i++)
os << v[i] << ofc;
}
/*------------------NON-MEMBER GLOBAL FUNCTIONS-----------------*/
template<typename T>
std::ostream & operator<<(std::ostream & os, const Stack<T> & a) {
a.print(os);
return os;
}
template <typename T>
bool operator==(const Stack<T> & a, const Stack<T> & b) {
if(a.size() != b.size())
return false;
else {
Stack<T> c = a;
Stack<T> d = b;
bool retVal = true;
while(!c.empty()) {
if(c.top() == d.top()) {
c.pop();
d.pop();
}
else {
retVal = false;
break;
}
}
return retVal;
}
}
template <typename T>
bool operator!=(const Stack<T> & a, const Stack<T> & b) {
return !(a == b);
}
template <typename T>
bool operator<(const Stack<T> & a, const Stack<T> & b) {
Stack<T> c = a;
Stack<T> d = b;
bool retVal = true;
while(!c.empty()) {
if(!(c.top() < d.top())) {
retVal = false;
break;
}
else {
c.pop();
d.pop();
}
}
return retVal;
}
Your operator< in stack.hpp has an extra closing curly brace which is closing the namespace early.
I have this implementation of queue:
#include<iostream>
using namespace std;
template <typename T>
struct elem_q
{
T inf;
elem_q<T>* link;
};
template <typename T = int>
class Queue
{
public:
Queue();
~Queue();
Queue(const Queue&);
Queue& operator= (const Queue&);
bool empty()const;
void push(const T&);
void pop(T&);
void head(T&) const;
void print();
int length();
private:
elem_q<T> *front;
elem_q<T> *rear;
void copyQueue(const Queue<T>);
void deleteQueue();
};
template <typename T>
Queue<T>::Queue()
{
front = rear = NULL;
}
template <typename T>
Queue<T>::~Queue()
{
deleteQueue();
}
template <typename T>
Queue<T>::Queue(const Queue<T>& r)
{
copyQueue(r);
}
template <typename T>
Queue<T>& Queue<T>::operator=(const Queue<T>& r)
{
if(this != &r)
{
deleteQueue();
copyQueue(r);
}
return *this;
}
template <typename T>
void Queue<T>::copyQueue(const Queue<T> r)
{
front = rear = NULL;
elem_q<T> *p = r.front;
while(p)
{
push(p->inf);
p = p->link;
}
}
template <typename T>
void Queue<T>::deleteQueue()
{
T x;
while (!empty())
{
pop(x);
}
}
template <typename T>
bool Queue<T>::empty() const
{
return rear == NULL;
}
template <typename T>
void Queue<T>::push(const T& x)
{
elem_q<T> *p = new elem_q<T>;
p->inf = x;
p->link = NULL;
if (rear) rear->link = p;
else front = p;
rear = p;
}
template <typename T>
void Queue<T>::pop(T& x)
{
if(empty())
{
cout<<"The queue is empty.\n";
}
else
{
elem_q<T> *q = front;
x = q->inf;
if (q == rear)
{
rear = NULL;
front = NULL;
}
else front = q->link;
delete q;
}
}
template <typename T>
void Queue<T>::head(T& x) const
{
if(empty())
{
cout<<"The queue is empty.\n";
}
else
{
x = front->inf;
}
}
template <typename T>
void Queue<T>::print()
{
T x;
while(!empty())
{
pop(x);
cout<<x<<" ";
}
cout<<endl;
}
template <typename T>
int Queue<T>::length()
{
T x;
int n = 0;
while(!empty())
{
pop(x);
n++;
}
return n;
}
template<typename T>
void minqueue(Queue<T> q,T& min,Queue<T>& newq)
{
T x;
q.pop(min);
while (!q.empty())
{
q.pop(x);
if (x < min)
{
newq.push(min);
min = x;
}
else newq.push(x);
}
}
template<typename T>
void sortQueue(Queue<T> q,Queue<T>& newq)
{
while(!q.empty())
{
T min;
Queue<T> q1;
minqueue(q , min ,q1);
newq.push(min);
q = q1;
}
}
template<typename T>
Queue<T> merge(Queue<T> p,Queue<T> q,const T& dummy)
{
p.push(dummy);
q.push(dummy);
Queue<T> r;
T x,y;
p.pop(x);
q.pop(y);
while (!p.empty() && !q.empty())
if (x < y)
{
r.push(x);
p.pop(x);
}
else
{
r.push(y);
q.pop(y);
}
if (!p.empty())
do
{
r.push(x);
p.pop(x);
}while (x != dummy);
else
do
{
r.push(y);
q.pop(y);
}while (y != dummy);
return r;
}
How can i redefine operator < and != because without them function minqueue,Sortqueue and merge do not work?Please help me...............................................
template <typename T>
struct elem_q
{
T inf;
elem_q<T>* link;
};
template <typename T>
bool operator <( const elem_q<T> &lhs, const elem_q<T> &rhs )
{
return ( lhs.inf < rhs.inf );
}
template <typename T>
bool operator ==( const elem_q<T> &lhs, const elem_q<T> &rhs )
{
return ( lhs.inf == rhs.inf );
}
template <typename T>
bool operator !=( const elem_q<T> &lhs, const elem_q<T> &rhs )
{
return ( !( lhs.inf == rhs.inf ) );
}
See how you already did this:
template <typename T>
Queue<T>& Queue<T>::operator=(const Queue<T>& r)
{
if(this != &r)
{
deleteQueue();
copyQueue(r);
}
return *this;
}
Overload the other operators you need, too.
Well, logical operators have rather expected syntax, looking like this:
bool ClassName::operator!=(const ClassName& other) const {
return //compare as apropriate.
}
However, I have to note two things:
First, you really need to go through the class design again -> there are wild inconsistencies in use of references, weird API and I am not even sure what exactly is minqueue is supposed to do, or rather why it does what it does.
Second, if you want to have queue that sorts itself, goes from minimal element and such, you should look up priority queue, or heap.
I have a class List:
#ifndef UTIL_H
#define UTIL_H
#include <iostream>
#include <exception>
namespace Util
{
class IndexOutOfBounds : public std::exception
{
virtual const char* what()
{
return "Index out of bounds";
}
};
template<class T>
class Iterator;
template <class T>
class ListNode
{
template<class R>
friend class Iterator;
template<class R>
friend class List;
public:
ListNode()
{
init();
}
ListNode(T info)
{
init();
this->info=info;
}
static void link(ListNode<T> first, ListNode<T> second)
{
first.next=&second;
second.prev=&first;
}
template<class R>
friend std::ostream& operator<< (std::ostream& out, const ListNode<R>& node);
template<class R>
friend std::istream& operator>> (std::istream& in, const ListNode<R>& node);
private:
T info;
ListNode<T>* next;
ListNode<T>* prev;
void init()
{
next=prev=this;
}
};
template<class T>
std::ostream& operator<< (std::ostream& out , const ListNode<T>& node)
{
out << node.info;
return out;
}
template<class T>
std::istream& operator>> (std::istream& in , const ListNode<T>& node)
{
in >> node.info;
return in;
}
template <class T>
class List
{
friend class ListNode<T>;
template <class R>
friend class Iterator;
private:
unsigned int length;
ListNode<T>* node;
public:
List()
{
node=new ListNode<T>();
length=0;
}
unsigned int size() const
{
return length;
}
void insert(int i,T info) throw()
{
ListNode<T>* ptr=node,*next_ptr;
try
{
if(i>(int)length || i<0)
throw IndexOutOfBounds();
for(int j=0;j<i;j++)
ptr=ptr->next;
next_ptr=ptr->next;
ptr->next=new ListNode<T>(info);
ptr->next->prev=ptr;
ListNode<T>::link(*(ptr->next),*next_ptr);
length++;
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void push_back(T info) throw()
{
try
{
insert(length,info);
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void push_front(T info) throw()
{
try
{
insert(0,info);
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void remove(int i) throw()
{
ListNode<T>* ptr=node,*next_ptr;
try
{
if(i>=length || i<0)
throw IndexOutOfBounds();
for(int j=0;j<i;j++)
ptr=ptr->next;
next_ptr=ptr->next->next;
delete ptr->next;
ListNode<T>::link(*ptr,*next_ptr);
length--;
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void pop_back() throw()
{
try
{
remove(length-1);
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
void pop_front() throw()
{
try
{
remove(0);
}
catch(IndexOutOfBounds& e)
{
throw e;
}
}
Iterator<T> begin() const
{
Iterator<T> result;
result.ptr=node->next;
return result;
}
Iterator<T> last() const
{
Iterator<T> result;
result.ptr=node->prev;
return result;
}
Iterator<T> end() const
{
Iterator<T> result;
result.ptr=node;
return result;
}
template <class R>
friend std::ostream& operator<< (std::ostream& out , const List<R>& l) ;
template <class R>
friend std::istream& operator>> (std::istream& in , const List<R>& l);
typedef Iterator<T> iterator;
};
template<class T>
std::ostream& operator<< (std::ostream& out ,const List<T>& l)
{
int k=0;
for(Iterator<T> i=l.begin();i!=l.end();++i)
out << *i << "\t";
return out;
}
template<class T>
std::istream& operator>> (std::istream& in , const List<T>& l)
{
for(Iterator<T> i=l.begin();i!=l.end();i++)
in >> *i;
return in;
}
template <class T>
class Iterator
{
friend class List<T>;
friend class ListNode<T>;
private:
ListNode<T>* ptr;
public:
Iterator()
{
ptr=NULL;
}
Iterator(const Iterator<T>& i)
{
ptr=i.ptr;
}
Iterator<T>& operator= (Iterator<T> i)
{
ptr=i.ptr;
return *this;
}
Iterator<T>& operator++ ()
{
ptr=ptr->next;
return *this;
}
Iterator<T> operator++ (int)
{
Iterator<T> i=*this;
++*this;
return i;
}
Iterator<T>& operator-- ()
{
ptr=ptr->prev;
return *this;
}
Iterator<T> operator-- (int)
{
Iterator<T> i=*this;
--*this;
return i;
}
T& operator* ()
{
return ptr->info;
}
template<class R>
friend bool operator!= (const Iterator<R>& i, const Iterator<R>& j);
template<class R>
friend bool operator== (const Iterator<R>& i, const Iterator<R>& j);
};
template <class T>
bool operator!= (const Iterator<T>& i, const Iterator<T>& j)
{
return i.ptr!=j.ptr;
}
template <class T>
bool operator== (const Iterator<T>& i, const Iterator<T>& j)
{
return i.ptr==j.ptr;
}
}
#endif
If in the main I try to print it:
int main(int argc, char** argv)
{
List<int> l;
for(int i=0;i<10;i++)
l.push_back(i);
std::cout << l;
return 0;
}
I get the screen full of numbers flowing, I have to kill the process from terminal.
So it goes into ain infinite loop and I don't understand why.
Maybe the Iterator operator != has some issue, I don't understand.
You don't terminate your linked list, in the last node the next pointer points back to the element itself.
Either fix this in the ListNode constructor (preferred), or when inserting new element to the list.