-1

I am working on a linked list class which contains a private nested node class. I want to advance n nodes forward in my list by using the overloaded addition operator but clang is giving me the error "overloaded 'operator+' must be a unary or binary operator (has 3 parameters)". I thought that the implicit this parameter disappeared when you declared it as a friend function.

First is my header file

 template <class T>
 class List
    {

  private:

    class ListNode
    {
      public:

        ListNode();


        ListNode(const T& ndata);


        friend ListNode* operator+(const ListNode* &node, int n);

        ListNode* next;

        ListNode* prev;

    };

  public:
    friend ListNode* operator+(const ListNode* &node, int n);

and my implementation is as follows:

template <class T>
typename List<T>::ListNode* List<T>::ListNode::operator+(const ListNode* &node, int n)
{
    ListNode* current = node;

    while (n--){
        if (current->next != 0)
            current = current->next;
    }
    return current;
}
Ami Tavory
  • 74,578
  • 11
  • 141
  • 185
Daryl Drake
  • 29
  • 1
  • 5

2 Answers2

1

Fundamentally, the problem with what you're trying to do is that it's oveloading an operator on pointers. This is problematic. Simplifying your code as much as possible for the point, the following does not build:

class foo{};

foo *operator+(foo *, int) {
    return nullptr;
}

int main() {}

The attempt gives:

$ g++ gl.cpp 
gl.cpp:5:26: error: ‘foo* operator+(foo*, int)’ must have an argument of class or enumerated type
 foo *operator+(foo *, int) {

If you really want to use operator+, the simplest way might be to use the member operator form:

template<class T>
class List {
    class ListNode {        ...
    public:
        ListNode &operator+(int n) {
            ListNode *current = this;

            while (n--)
               if (current->next != 0)
                   current = current->next;

           return *current;
        }
    };
    ...
};

However, this is a bit misleading, as you're not actually adding an integer to the node, but rather getting a next node. A next method is probably clearer:

template<class T>
class List {
    class ListNode {        ...
    public:
        ListNode *next(int n) {
            ListNode *current = this;

            while (n--)
                if (current->next != 0)
                   current = current->next;

            return current;
        }
    };
    ...
};
Community
  • 1
  • 1
Ami Tavory
  • 74,578
  • 11
  • 141
  • 185
  • I meant to put node instead of this but I am still getting the same error, I am confused as to how to define it as a free function/ what that means. – Daryl Drake Sep 28 '16 at 19:46
1

As already stated, overloading operators on pointers is problematic, and again, the easiest thing to do would be make operator+ a member function. However, there is a way to get the behavior you want...

The trick is to wrap the pointer in an object that acts like a pointer (commonly known as an iterator).

A working example to demonstrate:

class List {
    struct Node {
        Node* next; int data;
    };
    Node* m_head{0};

public:
    // the fake pointer type.
    struct Iter {
        Iter(Node* initial = 0)
            : m_base(initial) {}
        Node* operator->()
        { return m_base; }
        bool operator!=(const Iter& other) const
        { return m_base != other.m_base; }
    private:
        Node* m_base;
    };

    // get head as fake pointer.
    Iter head()
    { return m_head; }
    void push_front(const int&);
};

void List::push_front(const int& x)
{
    Node* n = new Node;
    n->data = x;
    n->next = m_head; m_head = n;
}

// non-member operator.
List::Iter operator+(List::Iter i, int count)
{
    for ( ; count > 0 && i != 0; count-- )
        i = i->next;
    return i;
}

int main(int argc, char* argv[])
{
    List list;
    for ( int i = 0; i < 10; i++ )
        list.push_front(i);
    for ( auto i = list.head(); i != 0; i = i+1 )
        std::cout << i->data << ' ';
    std::cout << std::endl;
    return 0;
}

For a more advanced example see here.

John Q.
  • 177
  • 4