ardas
ardas

Reputation: 33

Overloading operator+ for linked lists

I'm a beginner and now I am trying to implement the class linked list which contains the function begin(). The function return well the first element in the list, but what i am trying to do is to return the iterator on the next position, for instance something like this:

List<int>::iterator iter2 = a.begin() + 2; // or iter2 = iter2 + 1;
cout <<iter2->data;

Where the output is garbage like 21213123..

So here I was thinking I should use an operator overloading+, here is my function:

template<class T>
Node<T>* operator+(const Node<T>& iter, const int& pos)
{
    cout << "in"; for testing, but seems that doesnt even entry here

    return NULL;
}

So can anyone help me? Thank you very much

P.S: Here is the class Node

 template<class T>
class Node {
public:
    T data;
    Node* next;
    Node() :data(0), next(NULL) {}
    Node(T val, Node<T>* pointer = NULL) :data(val), next(pointer) {}

};

and list class

template<class T>
class List {


public:
    typedef Node<T>* iterator;
    typedef const Node<T>* const_iterator;
    //constructors
    List() { item = NULL; counter = 0; }
    explicit List(int val) :counter(1) { item = new Node<T>(val); }
    ~List() { // to be made 
    }
    //public functions
    int size() { return counter; }

    iterator begin() {
        return item;
    }
    iterator end()
    {
        iterator last = item;
        while (last->next != NULL)
        {
            last = last->next;
        }
        return last;

    }

    void push_front(const int& val) {
        iterator newNode = new Node<T>(val, item);
        item = newNode;

        counter++;
    }
    void append(const int& val)
    {
        iterator newnode = new Node<T>(val);
        newnode->next = NULL;
        iterator last = item;
        if (item == NULL)
        {
            item = newnode;
            return;
        }
        while (last->next != NULL)
            last = last->next;

        last->next = newnode;

        counter++;
    }

    int operator[](const int&);

private:

    iterator item;
    int counter;
};

Upvotes: 1

Views: 239

Answers (2)

sp2danny
sp2danny

Reputation: 7644

iterator for a linked list cannot be a pointer, it needs to be something like:

struct iterator
{   
    typedef int difference_type;
    typedef T* pointer;
    typedef T& reference;
    typedef iterator_category std::bidirectional_iterator_tag

    iterator();
    iterator& operator++();
    iterator& operator--();
    iterator operator++(int);
    iterator operator--(int);
    T& operator*();
    T* operator->();
    bool operator==(iterator rhs) const;
    bool operator!=(iterator rhs) const;
private:
    iterator(Node*);
    Node* node;
};

Upvotes: 0

templatetypedef
templatetypedef

Reputation: 372714

Let's take a look at your begin function:

typedef Node<T>* iterator;
iterator begin() {
    ...
}

This function returns a Node<T>*, a pointer to a Node<T> object. As a result, when you write

list.begin() + 2;

C++ interprets this to mean "I've got a pointer, and I've got a number, so I'll step that pointer forward the appropriate number of steps."

You're then asking - well, wait a minute, why isn't this overloaded operator getting called?

template<class T>
Node<T>* operator+(const Node<T>& iter, const int& pos) {
    ...
}

Take a look at the argument types. This function says "if someone tries adding together an honest-to-goodness Node<T> object and an int, here's what I'd like you to do." The problem is that the code

list.begin() + 2

doesn't try adding an honest-to-goodness Node<T> object and an integer. Instead, it adds a pointer to a Node<T> object and an integer. And since those types don't match your overloaded operator, it won't even try calling the overloaded operator.

Unfortunately, in C++ you can't overload an operator between two primitive types, so there's no way to write a version of operator+ that takes in a Node<T>* and an int, so the fix here isn't as simple as "just make your operator+ function take in a Node<T>*.

Rather, I'd suggest making your iterator type an actual class or struct rather than a raw pointer. Your iterator will likely work by keeping track of a pointer to some Node<T> somewhere, but fundamentally the iterator isn't actually just that pointer itself. For example, you might try something like this:

template <class T>
class List {
public:
    class iterator {
    public:
        // some other things, and
        iterator operator+ (int step) const;

    private:
        // some other things, and
        Node<T>* current;
    };

    // some other things, and
    iterator begin();
};

Now, you can overload operator+ on the List<T>::iterator type. That implementation of operator+ can then update the stored Node<T>* inside the iterator.

Hope this helps!

Upvotes: 1

Related Questions