简体   繁体   中英

Dereference operator doesn't work (syntax issue?)

So I have a very dumbed down example of a singly-linked list implementation. And I have a begin function as a public member of the forward_list which returns a pointer to the first (root) element of the list.

Now since it returns a pointer to a _node object which contains various members, it is to my understanding that a dereference operator overload must be provided in order for _node to know what to return when dereferenced.

In the dereference operator definition I tried returning the value of the _node , which all seems quite logical, since begin returns a _node that would mean dereferencing begin would give me the value behind the _node . Apparently not, as the MSVC compiler tells me: binary '<<': no operator found which takes a right-hand operand of type '_node<TType>' (or there is no acceptable conversion)

#include <iostream>
#include <cstddef>

//forward declarations
template<class TType> class forward_list;

template<class TType>
class _node
{
private:
    TType key;
    _node *next;

    friend class forward_list<TType>;
public:
    TType operator*() { return this->key; } //problem is here
};

template<class TType>
class forward_list
{
private:
    _node<TType> *_root;
    _node<TType> *_tail;

    std::size_t _size;
private:
    void _add_node_front(const TType &new_key)
    {
        _node<TType> *new_node = new _node<TType>{ new_key, this->_root };

        if (this->_root == nullptr)
            this->_tail = new_node;

        this->_root = new_node;

        ++this->_size;
    }
public:
    forward_list() : _root(nullptr), _tail(nullptr), _size(0) {}

    void push_front(const TType &new_key) { this->_add_node_front(new_key); }

    _node<TType> *begin() { return this->_root; }
};

int main()
{
    forward_list<int> l;
    l.push_front(23);
    l.push_front(57);
    l.push_front(26); //26 57 23

    std::cout << *l.begin(); //expected to print out "26"
}

EDIT:: Thanks to Joachim Pileborg for suggesting. Works like a charm with the following change:

_node<TType> begin() { return *this->_root; }

You are returning a pointer:

_node<TType> *begin();

so you need to dereference that twice:

  1. dereference the pointer
  2. call your operator (it's defined for _node<...> , not for _node<...> * , it won't be called instead of the simple dereference)

Perhaps, a better would be to replace

TType operator*();

with user defined conversions, which will return this->key; :

operator TType& ();
operator TType const& () const;

and you won't need that second dereference.

The problem is that you dereference the pointer which gives you an object of type _node<int> which you can then again use the dereference operator on.

So you could solve your problem by using two dereference operators:

**i.begin()

Another solution is that you return the node by value instead of returning a pointer to it, which is how iterators functions in the standard containers.

The immediate reason of thee error is that begin returns a _node* , and your overloaded operator* needs a _node .

If you want to implement a standard-conforming container, your begin operator should return an iterator (by value), not a (pointer to a) node. This iterator thing should implement operator* (and also operator++ and a bunch of other stuff). The node class is not suitable as an iterator. You need a separate class. Google something like "implementing my own iterators".

If you implement iterators, don't expose your node class to end users.

If you want just any list that doesn't conform to anything in particular, you will probably be better off not overloading any operators. Use getValue or something.

The problem is on this line:

std::cout << *l.begin(); //expected to print out "26"

You haven't defined operator<< to stream one of these objects to an ostream.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM