vendredi 27 mai 2022

Conversion between Iterator and ConstIterator

I have a linked list that contains a pointer to the first and last node and size which indicates how many nodes are there in the list. I've implemented both Iterator and ConstIterator, ATM ConstIterator only works for const lists, and Iterator for lists, and I want it that Iterator to work for both lists and const lists, this is what I've done so far:

Node class:

template<class T>
class Node {
    public:
        Node(const T& t);
        ~Node()=default; // Destructor set to default
        Node(const Node&) = default; // Copy Constructor set to default
        Node& operator=(const Node&) = default; // Assignment operator set to default
        T& getData();
        const T& getData() const;
        Node* getNext() const;
        void setNext(Node<T>* newNext);
    private:
        T m_data;
        Node* m_nextNode;
};

template<class T>
Node<T>::Node(const T& t) {
    this->m_data=t;
    this->m_nextNode=nullptr;
}

template<class T>
Node<T>* Node<T>::getNext() const {
    return this->m_nextNode;
}

template<class T>
T& Node<T>::getData() {
    return this->m_data;
}

template<class T>
const T& Node<T>::getData() const {
    return this->m_data;
}

template<class T>
void Node<T>::setNext(Node<T>* newNext) {
    this->m_nextNode=newNext;
}

Queue class:

template<class T>
class Queue {
    public:
        static const int SIZE_EMPTY=0;
        Queue();
        ~Queue(); // Destructor
        Queue(const Queue&); // Copy Constructor
        Queue& operator=(const Queue&); // Assignment operator
        void pushBack(const T& t);
        T& front();
        const T& front() const;
        void popFront();
        int size() const;
        class Iterator;
        Iterator begin();
        Iterator end();
        class ConstIterator;
        ConstIterator begin() const;
        ConstIterator end() const;
        class EmptyQueue {};
    private:
        Node<T>* m_head;
        Node<T>* m_tail;
        int m_size;
};

template<class T>
Queue<T>::Queue() {
    this->m_head=nullptr;
    this->m_tail=nullptr;
    this->m_size=Queue<T>::SIZE_EMPTY;
}

template<class T>
Queue<T>::~Queue() {
    while(this->m_head) {
        this->popFront();
    }
}

template<class T>
Queue<T>::Queue(const Queue<T>& queue) {
    this->m_head=nullptr;
    this->m_tail=nullptr;
    this->m_size=Queue<T>::SIZE_EMPTY;
    for(typename Queue<T>::ConstIterator i = queue.begin();i != queue.end();++i) {
        try {
            this->pushBack(*i);
        } catch(typename Queue<T>::ConstIterator::InvalidOperation& e) {
            throw e;
        }
    }
}

template<class T>
void Queue<T>::pushBack(const T& t) {
    try {
        Node<T>* newNode=new Node<T>(t);
        if(this->m_size==Queue<T>::SIZE_EMPTY) {
            this->m_head=newNode;
            this->m_tail=newNode;
        } else {
            this->m_tail->setNext(newNode);
            this->m_tail=newNode;
        }
        this->m_size+=1;
    } catch(std::bad_alloc& e) {
        throw e;
    }
}

Queue<T>::Iterator class:

template<class T>
class Queue<T>::Iterator {
    public:
        T& operator*();
        Iterator& operator++();
        Iterator operator++(int);
        bool operator==(const Iterator& iterator) const;
        bool operator!=(const Iterator& iterator) const;
        Iterator(const Iterator&)=default;
        Iterator& operator=(const Iterator&)=default;
        class InvalidOperation {};
    private:
        Node<T>* node;
        Iterator(Node<T>* node);
        friend class Queue<T>;
};

template<class T>
Queue<T>::Iterator::Iterator(Node<T>* node) {
    this->node=node;
}

template<class T>
T& Queue<T>::Iterator::operator*() {
    if(this->node==nullptr) {
        throw Queue<T>::Iterator::InvalidOperation();
    }
    return this->node->getData();
}

template<class T>
typename Queue<T>::Iterator& Queue<T>::Iterator::operator++() {
    if(this->node==nullptr) {
        throw Queue<T>::Iterator::InvalidOperation();
    }
    this->node=node->getNext();
    return *this;
}

template<class T>
typename Queue<T>::Iterator Queue<T>::Iterator::operator++(int) {
    if(this->node==nullptr) {
        throw Queue<T>::Iterator::InvalidOperation();
    }
    Iterator result = *this;
    ++*this;
    return result;
}

template<class T>
bool Queue<T>::Iterator::operator==(const Iterator& iterator) const {
    return this->node==iterator.node;
}

template<class T>
bool Queue<T>::Iterator::operator!=(const Iterator& iterator) const {
    return !(*this==iterator);
}

template<class T>
typename Queue<T>::Iterator Queue<T>::begin() {
    return this->m_head;
}

template<class T>
typename Queue<T>::Iterator Queue<T>::end() {
    return nullptr;
}

Queue<T>::ConstIterator class:

template<class T>
class Queue<T>::ConstIterator {
    public:
        const T& operator*();
        ConstIterator& operator++();
        ConstIterator operator++(int);
        bool operator==(const ConstIterator& constIterator) const;
        bool operator!=(const ConstIterator& constIterator) const;
        ConstIterator(const ConstIterator&)=default;
        ConstIterator& operator=(const ConstIterator&)=default;
        class InvalidOperation {};
    private:
        const Node<T>* node;
        ConstIterator(const Node<T>* node);
        friend class Queue<T>;
};

template<class T>
Queue<T>::ConstIterator::ConstIterator(const Node<T>* node) {
    this->node=node;
}

template<class T>
const T& Queue<T>::ConstIterator::operator*() {
    if(this->node==nullptr) {
        throw Queue<T>::ConstIterator::InvalidOperation();
    }
    return this->node->getData();
}

template<class T>
typename Queue<T>::ConstIterator& Queue<T>::ConstIterator::operator++() {
    if(this->node==nullptr) {
        throw Queue<T>::ConstIterator::InvalidOperation();
    }
    this->node=node->getNext();
    return *this;
}

template<class T>
typename Queue<T>::ConstIterator Queue<T>::ConstIterator::operator++(int) {
    if(this->node==nullptr) {
        throw Queue<T>::ConstIterator::InvalidOperation();
    }
    ConstIterator result = *this;
    ++*this;
    return result;
}

template<class T>
bool Queue<T>::ConstIterator::operator==(const ConstIterator& constIterator) const {
    return this->node==constIterator.node;
}

template<class T>
bool Queue<T>::ConstIterator::operator!=(const ConstIterator& constIterator) const {
    return !(*this==constIterator);
}

template<class T>
typename Queue<T>::ConstIterator Queue<T>::begin() const {
    return this->m_head;
}

template<class T>
typename Queue<T>::ConstIterator Queue<T>::end() const {
    return nullptr;
}

main for tests:

    Queue<int> queue1;
    for (int i = 1; i <= 10; i++) {
        queue1.pushBack(i);
    }
    const Queue<int> constQueue = queue1;
    for(Queue<int>::Iterator i = constQueue.begin(); i != constQueue.end(); ++i) {
        std::cout << *i << std::endl;
    }

Aucun commentaire:

Enregistrer un commentaire