Making a tempalte class internal of another class


I am a newbie in C++. My template classes work fine (at least it seems like so). Now I'd like to make class Iterator an internal class of List. Could you help me on that please?

I have been searching on line for examples but I couldn't find anything to help me understand how it's done.


Below I pasted my list.h and list.cpp files for you to see.

#ifndef LIST_H
#define LIST_H

#include <string>

template <typename T> class Element;
template <typename T> class Iterator;

template <typename T>
class List {
public:
List();
List(const List<T> & other);//copy constructor
~List();
void add(const T& s);
void insert(const Iterator<T>& pos, const T& s);
void remove(Iterator<T>& pos);
void free();
void copy(const List<T>& other);
const List<T> & operator=(const List<T>& other);

Iterator<T> getFirst() const;
Iterator<T> getLast() const;
private:
Element<T>* firstElement;
Element<T>* lastElement;
};
template <typename T>
class Iterator {
public:
Iterator();
T& get() const;
void next();
void prev();

bool equal(const Iterator& b) const;
void operator++(int junk);
void operator++();
T& operator*();
bool operator==(const Iterator& other) const;
bool operator!=(const Iterator& other) const;

private:
Element<T>* position;
Element<T>* last;
friend class List<T>;
};
#endif

/list.cpp
#include "list.h"
#include <string>
#include <iostream>

using namespace std;

template <typename T>
class Element {
public:
Element(const T& s);

private:
T value;
Element<T>* prev;
Element<T>* next;
friend class List<T>;
friend class Iterator<T>;
};

template <typename T>
Element<T>::Element(const T &s) {
value = s;
prev = next = NULL;
}

template <typename T>
Iterator<T>::Iterator() {
position = last = NULL;
}

template <typename T>
T& Iterator<T>::get() const {
return position->value;
}

template <typename T>
void Iterator<T>::next() {
position = position->next;
}

template <typename T>
void Iterator<T>::prev() {
if(position == NULL) {
position = last;
} else {
position = position->prev;
}
}

template <typename T>
bool Iterator<T>::operator ==(const Iterator& other) const {
return (this->position == other.position);
}

template <typename T>
bool Iterator<T>::operator !=(const Iterator& other) const {
return (this->position != other.position);
}

template <typename T>
void Iterator<T>::operator ++(int junk) {
this->position = this->position->next;
}

template <typename T>
void Iterator<T>::operator ++() {
this->position = this->position->next;
}

template <typename T>
T& Iterator<T>::operator *() {
return this->position->value;
}

template <typename T>
bool Iterator<T>::equal(const Iterator& b) const {
return position==b.position;
}

template <typename T>
List<T>::List() {
firstElement = lastElement = NULL;
}

//copy constructor
template <typename T>
List<T>::List(const List<T> & other) {
firstElement = lastElement = NULL;
copy(other);
}

template <typename T>
void List<T>::copy(const List<T>& other) {
if(&other == this) {
return;
}
free();
for(Iterator<T> pos=other.getFirst(); pos!=other.getLast(); pos++ ){
this->add(pos.get());
}
}

template <typename T>
List<T>::~List() {
free();
}

template <typename T>
void List<T>::free() {
for(Iterator<T> pos=this->getFirst(); pos!=this->getLast();){
Iterator<T> temp = pos;
pos++;
this->remove(temp);
}
//important!!
}

template <typename T>
const List<T> & List<T>::operator=(const List<T>& other) {
copy(other);
return *this;
}

template <typename T>
Iterator<T> List<T>::getFirst() const {
Iterator<T> it;
it.position = firstElement;
it.last = lastElement;
return it;
}

template <typename T>
Iterator<T> List<T>::getLast() const {
Iterator<T> it;
it.position = NULL;
it.last = lastElement;
return it;
}

template <typename T>
void List<T>::add(const T& s) {
Iterator<T> last = getLast();
insert(last, s);
}

template <typename T>
void List<T>::insert(const Iterator<T>& pos, const T& s) {

Element<T>* newElement = new Element<T>(s);

if(lastElement==NULL && firstElement==NULL) {
//list is empty
firstElement = newElement;
lastElement = newElement;
} else {
//list is not empety
if(pos.position == NULL) {
lastElement->next = newElement;
newElement->prev = lastElement;
lastElement = newElement;
} else if(pos.position == firstElement){
firstElement->prev = newElement;
newElement->next = firstElement;
firstElement = newElement;
} else {
newElement->next = pos.position;
newElement->prev = pos.position->prev;
pos.position->prev->next = newElement;
pos.position->prev = newElement;
}

}
}

template <typename T>
void List<T>::remove(Iterator<T>& pos) {

if(lastElement==NULL && firstElement==NULL) {
//list is empty, nothing to remove
return;
} else {
//list is not empety
if(pos.position == NULL) {
return;
} else if(pos.position == firstElement){
firstElement = firstElement->next;
} else {
pos.position->prev->next = pos.position->next;
pos.position->next->prev = pos.position->prev;
}
delete pos.position;
}
}

Please use code tags so your code is formatted neatly.

What problems are you having?

I would look at how STL list implements its iterators and follow the same pattern. To make your own iterator that is standards compliant is not easy.
Please write a concrete question/problem. You can include template classes in other (template) classes without problems. However, remember that you require the "typename"-keyword for dependent names (i.e., if your container class has a value_type, the iterator class will have to make a typedef typename container::value_type value_type; if it wants to use this type as 'value_type')

To make your own iterator that is standards compliant is not easy.

Just inherit from std::iterator, and you pretty much ensure that it is standard (i.e., stl) compliant. You also might want to have a look at the appropriate section in "Generic Programming and the STL", which describes all requirements for each iterator category (good as a checklist).
Topic archived. No new replies allowed.