Exercise 3.13 Add support for operator-- to the List iterator classes
3.14 Looking ahead in an STL iterator requires an application of operator++, which in turn advances the iterator. In some cases looking at the next item in the list, without advancing to it, may be preferable. Write the member function with the declaration
const_iterator operator_*int k) const;
to facilitate this in a general case. The binary operator+ returns an iterator that corresponds to k positions ahead of current.
3.15Add the splice operation to the List class. The method declaration:
void splice(iterator position, List<t>& lst);
removes all the items from lst, placing them prior to position in List *this, lst and *this must be different lists. Your routine must run in constant time.
3.16 Add reverse iterators to the STL List class implementation. Define reverse_iterator and const_reverse_iterator. Add the methods rbegin and rend to return appropriate reverse iterators representing the position prior to the endmarker and the position that is the header node. Reverse iterators internally reverse the meaning of the ++and --operators. You should be able to print a list L in reverse by using the code
List<Object>::reverse_iterator itr=L.rbegin();
while(itr != L.rend())
cout << *itr++ << endl;
3.17 Modify the List class to provide stringent iterator checking by using the ideas suggested at the end of Section 3.5
//list.hpp
#ifndef LIST_HPP__
#define LIST_HPP__
#include <iostream>
#include <cassert>
const int Null = 0;
template<typename Object>
class List {
private:
class Node {
public:
Node(const Object& d = Object(), Node* p = Null, Node* n = Null) : data(d), next(n), prev(p) {}
public:
Object data;
Node* next;
Node* prev;
};
public:
class const_iterator {
public:
const_iterator() : current(Null){}
const Object& operator* () const { return retrieve(); }
const_iterator& operator++()
{
current = current->next;
return *this;
}
const_iterator& operator++(int)
{
const_iterator old = *this;
++(*this);
return old;
}
const_iterator& operator+(int n) const
{
for(int i = 0; i < n; ++i)
++(*this);
return *this;
}
const_iterator& operator--()
{
current = current->prev;
return *this;
}
const_iterator& operator--(int)
{
const_iterator old = *this;
--(*this);
return old;
}
bool operator==(const const_iterator& rhs) const
{
return current == rhs.current;
}
bool operator!=(const const_iterator& rhs) const
{
return !(*this == rhs);
}
protected:
Node* current;
Object& retrieve() const { return current->data; }
const_iterator(const List<Object> &lst, Node* p) : theList(&lst), current(p) {}
void assertValid()
{
assert(theList != Null || current != Null || current != theList->head);
}
const List<Object> *theList;
friend class List<Object>;
};
class iterator : public const_iterator {
public:
iterator(){}
Object& operator*() { return retrieve(); }
Object& operator*() const { return retrieve(); }
iterator& operator++()
{
current = current->next;
return *this;
}
iterator& operator++(int)
{
Node old = *this;
++(*this);
return old;
}
iterator& operator+(int n)
{
for(int i = 0; i < n; ++i)
++(*this);
return *this;
}
iterator& operator--()
{
current = current->prev;
return *this;
}
iterator& operator--(int)
{
Node old = *this;
--(*this);
return old;
}
bool operator==(const iterator& rhs) const
{
return current == rhs.current;
}
bool operator!=(const iterator& rhs) const
{
return !(*this == rhs);
}
private:
iterator(List<Object> &lst, Node *p) : const_iterator(lst, p) {}
friend class List<Object>;
};
class const_reverse_iterator {
public:
const_reverse_iterator() : current(Null), theList(Null) {}
const Object* operator*() const
{ return current->data; }
const_reverse_iterator& operator++()
{
current = current->prev;
return *this;
}
const_reverse_iterator operator++(int)
{
const_reverse_iterator old = *this;
++(*this);
return old;
}
const_reverse_iterator& operator--()
{
current = current->next;
return *this;
}
const_reverse_iterator operator--(int)
{
const_reverse_iterator old = *this;
--(*this);
return old;
}
bool operator==(const const_reverse_iterator& rhs)
{ return current == rhs.current; }
bool operator!=(const const_reverse_iterator& rhs)
{ return !(*this == rhs); }
protected:
const_reverse_iterator(List<Object> &lst, Node *p) : theList(&lst), current(p){}
Node* current;
List<Object>* theList;
friend class List<Object>;
};
class reverse_iterator : public const_reverse_iterator {
public:
reverse_iterator(){}
Object& operator*()
{ return current->data; }
const Object& operator*() const
{ return current->data; }
reverse_iterator& operator++()
{
current = current->prev;
return *this;
}
reverse_iterator operator++(int)
{
reverse_iterator old = *this;
++(*this);
return old;
}
reverse_iterator& operator--()
{
current = current->next;
return *this;
}
reverse_iterator operator--(int)
{
reverse_iterator old = *this;
--(*this);
return old;
}
bool operator==(const reverse_iterator& rhs)
{ return rhs.current == current; }
bool operator!=(const reverse_iterator& rhs)
{ return !(*this == rhs); }
private:
reverse_iterator(List<Object>& lst, Node* p) : const_reverse_iterator(lst,p){}
friend class List<Object>;
};
public:
List()
{
init();
}
List(const List& rhs)
{
init();
*this = rhs;
}
~List()
{
clear();
delete head;
delete tail;
}
List& operator=(const List& rhs)
{
if(rhs == *this)
return *this;
clear();
for(const_iterator it = rhs.begin(); it != rhs.end(); ++ it)
push_back(*it);
return *this;
}
iterator begin() { return iterator(*this, head->next); }
const_iterator begin() const { return const_iterator(*this, head->next); }
iterator end() { return iterator(*this, tail); }
const_iterator end() const { return const_iterator(*this, tail); }
reverse_iterator rbegin() { return reverse_iterator(*this, tail->prev); }
const_reverse_iterator rbegin() const { return const_reverse_iterator(*this, tail->prev); }
reverse_iterator rend() { return reverse_iterator(*this, head); }
const_reverse_iterator rend() const { return const_reverse_iterator(*this, head); }
unsigned int size() const { return thesize; }
bool empty() const { return thesize == 0; }
void clear()
{
while(!empty())
pop_front();
}
Object& front() { return *begin(); }
const Object& front() const { return *begin(); }
Object& back() { return *(--end()); }
const Object& back() const { return *(--end()); }
void push_front(const Object& ob)
{
insert(begin(), ob);
}
void push_back(const Object& ob)
{
insert(end(), ob);
}
void pop_front() { erase(begin()); }
void pop_back() { erase(--end()); }
void splice(iterator pos, List<Object>& lst)
{
if(lst.head == this->head)
return;
Node* p = pos.current;
p->prev->next = lst.head->next;
lst.head->next->prev = p->prev;
p->prev = lst.tail->prev;
lst.tail->prev->next = p;
thesize += lst.size();
lst.head->next = lst.tail;
lst.tail->prev = lst.head;
lst.thesize = 0;
}
iterator insert(iterator it, const Object& ob)
{
it.assertValid();
if(it.theList != this)
std::cerr << "Not the same list/n"; //should replaced by throw exceptions when use
else
{
Node* p = it.current;
++thesize;
return iterator(*this, p->prev = p->prev->next = new Node(ob, p->prev, p));
}
}
iterator erase(iterator it)
{
it.assertValid();
if(it.theList != this)
std::cerr << "Not the same list/n"; //should replaced by throw exceptions when use
else
{
Node* p = it.current;
iterator retVal = iterator(*this, p->next);
p->prev->next = p->next;
p->next->prev = p->prev;
delete p;
--thesize;
return retVal;
}
}
iterator erase(iterator start, iterator end)
{
for(iterator it = start; it != end; )
it = erase(it);
return end;
}
private:
unsigned int thesize;
Node* head;
Node* tail;
void init()
{
thesize = 0;
head = new Node();
tail = new Node();
head->next = tail;
tail->prev = head;
}
};
#endif