in c++ my operator overloading prefix not work

Viewed 250

Question has been modified

I have a list class (like linking list) that contain add() and begin() functions add() function that adds to tail begin() function that returns the address of the first element (head)

i try to make my class support for-range for(:) so i try to implementation begin(), end() and operator++() functions, But I got stuck on operator++() it doesn't work (read the note below)

New Addition

the problem is that the i is a Node Pointer so I can't do this ++i that will just increase the address of the pointer and it will not run the operator++() because it is a Node Pointer not an Object from Node struct so when i do this ++(*i) it will run the operator++()

#include <iostream>
using namespace std;
class List
{
    struct Node
    {
        int info;
        Node *next;
        Node(int val) : info(val), next(NULL) {}
        
       Node * operator++(){ // not working
            cout << "i am alive\n";
            *this = *this->next;
            return this;
        }
    };
    Node *head = NULL;
    Node *tail = NULL;

public:
    void add(int val) // add to tail, O(1)
    {
        Node *temp = new Node(val);

        if (!head)
        {
            head = temp;
            tail = temp;
            return;
        }

        tail->next = temp;
        tail = temp;
    }
    Node *begin()
    {
        return head;
    }
};
int main()
{
    List l;
    l.add(2);
    l.add(5);
    l.add(10);
        
    auto i = l.begin(); // *i is 2
    ++i; 
    cout << (*i).info; // output is 0
}

NOTE THAT: if i do that, it will work and print 5

    auto i = l.begin(); // *i is 2
    i->operator++(); // will work
    // ++(*i); //also will work
    cout << (*i).info; // output is 5
3 Answers

Your implementation approach to the increment operator is wrong. It is not supposed to return the incremented value. Instead, it should increment the value of the object it is called on. Then, it should return a reference to that object for the prefix variant or a copy of the former value in the postfix variant.

The problem with your code is also that it compares apples to oranges. Your i is a pointer and ++i will just increment that pointer. It doesn't care whether your class implements an increment operator. In order to invoke that, you need ++*i.

Thank you everyone, I solved the problem by implementing the Iterator Class by myself like what you said

my class is now support for range for(:)

#include <iostream>
using namespace std;

class List
{
    struct Node
    {
        int info;
        Node * next;
        Node(int val): info(val), next(NULL) {}
    };

    class Iterator
    {
        Node * ptr;
    public:
        Iterator(Node *p): ptr(p) {}

        Iterator & operator=(Node * Np)
        {
            ptr = Np;
            return *this;
        }

        bool operator!=(Iterator & it)
        {
            return this->ptr != it.ptr;
        }

        Iterator &operator++()
        {
            if (ptr)
            {
                ptr = ptr->next;
                return * this;
            }
        }

        Iterator &operator++(int)
        {
            Iterator it = *this;
            ++(*this);
            return it;
        }

        int operator*()
        {
            return ptr->info;
        }
    };

    Node *head = NULL;
    Node *tail = NULL;

public:
    void add(int val)   // add to tail, O(1)
    {
        Node *temp = new Node(val);

        if (!head)
        {
            head = temp;
            tail = temp;
            return;
        }

        tail->next = temp;
        tail = temp;
    }

    Iterator begin()
    {
        return Iterator(head);
    }

    Iterator end()
    {
        return Iterator(NULL);
    }
};
int main()
{
    List l;
    l.add(2);
    l.add(5);
    l.add(10);

    auto i = l.begin();
    ++i;
    cout << *i <<'\n'; // output 5
    
    for(auto it : l){
        cout << it <<' '; // output 2 5 10
    }
}

You can easily implement a const iterator-like object as below, using Node. If you want to be able to modify the list through the iterator, however, you might have to create a new class.

Node &operator++(){
    return *this = *this->next;
}

int operator*() {
  return this->info;
}

Node cbegin() {
  return *head;
}
Related