Оператор разыменования для пользовательского итератора в пользовательском двусвязном списке, бинарный оператор не найден - PullRequest
0 голосов
/ 20 декабря 2018

Я реализую общий контейнер двусвязного списка с вложенным пользовательским итератором в классе контейнера.Моя проблема заключается в том, что при компиляции я получаю:

Ошибка C2678 бинарный '*': не найден оператор, который принимает левый операнд типа 'const List :: ListIter' (или нет приемлемогопреобразование)

Эта ошибка указывает на попытку разыменования, например, итератора в строке 246.operator* для итератора реализовано в классе итераторов, но компилятор, похоже, не может найти перегрузку.

Все остальное, кажется, компилируется просто отлично при сборке

using std::cout;
template<class T> class List {
template<class T>
class Node;


public:
template <class T>
class Link {
public:
    friend class List<T>;
    Link* _next, *_prev;
    Link(Link *n, Link *p) : _next(n), _prev(p) {}
    Node<T>* Next() { return static_cast<Node<T>*>(_next); }
    Node<T>* Prev() { return static_cast<Node<T>*>(_next); }


};

template<class T>
class Node :public Link<T> {


public:
    friend class List<T>;
    Node(const T& data = NULL, Link<T> *n = NULL, Link<T> *p = NULL) :_data(data), Link<T>(n, p) {}
    T _data;
};


public:
template<class T> class ListIter {
public:
    typedef ptrdiff_t difference_type;
    typedef T value_type;
    typedef T* pointer;
    typedef T& reference;
    typedef std::bidirectional_iterator_tag iterator_category;//behvöber fixas
    ListIter(Node<T>* p) {
        _ptr = p;
    }

    ListIter() {
        _ptr = nullptr;
    }

    ListIter(const ListIter& other) {
        _ptr = other._ptr;
    }

    ListIter& operator=(const ListIter& other) {
        if (_ptr == other._ptr) {
            return *this;
        }
        else {
            _ptr = other._ptr;
            return *this;
        }
    }

    T & operator*() {
        return _ptr->_data;
    }

    T* operator->() {
        return &_ptr->_data;
    }

    ListIter& operator++() {
        _ptr = static_cast<Node<T>*>(_ptr->_next);
        return *this;
    }

    ListIter& operator--() {
        _ptr = static_cast<Node<T>*>(_ptr->Prev());
        return *this;
    }

    ListIter operator++(int) {
        ListIter temp(*this);
        _ptr = static_cast<Node<T>*>(_ptr->_next);
        return temp;
    }

    ListIter operator--(int) {
        ListIter temp(*this);
        _ptr = static_cast<Node<T>*>(_ptr->Prev());
        return temp;
    }
private:
    Node<T>* _ptr;
};
using iterator = ListIter<T>;

~List() {

    int counter = 0;
    Link<T> *curr = _head;
    while (curr != nullptr)
    {
        Link<T> *remove = curr;
        curr = curr->_next;
        delete remove;
        counter++;
    }

    cout << "removed" << counter << std::endl;
}


List() :_head(nullptr) {};

List(const List& other) {

    if (other._head == nullptr) {
        _head = nullptr;
    }
    _head = new Node<T>(other._head->_data);
    Node<T> *tempOther = _head->Next();
    while (tempOther != other._head) {
        push_back(tempOther->_data);
        tempOther = tempOther->Next();
    }
}


List(List&& other) {
    _head = other._head;
    other._head = nullptr;
}

List(const char* other) {
    int i = 0;
    while (other[i] != '\0') {
        push_front(other[i]);
        i++;
    }
}

List& operator=(const List* other) {
    if (*this == *other) {
        return *this;
    }
    else {
        if (other->_head != NULL) {
            Link<T> *curr = _head;
            while (curr != nullptr)
            {
                Link<T> *remove = curr;
                curr = curr->_next;
                delete remove;
            }
            _head = new Node<T>(other->_head->_data);
            if (other->_head->Prev() != NULL) {
                Node<T> *prev = other->_head->Prev();
                while (prev != NULL) {
                    push_back(prev->_data);
                    prev = prev->Prev();
                }
            }
            other->~List();
        }
        else {
            throw std::exception("list empty");
        }
    }
    return *this;
}

List& operator=(List&& other) {
    while (_head->_next != _head)
    {
        Link<T> *remove = _head->_next;
        _head->_next = remove->_next;
        delete remove;
    }
    delete _head;
    _head = other._head;
    return *this;
}

T& front() {
    if (_head->_next != NULL) {
        return _head->Next()->_data;
    }
    else {
        throw std::exception("list is empty");
    }
}
T& back() {
    if (!empty()) {
        Node<T> *last = _head->Prev();

        return last->_data;
    }
    else {
        throw std::exception("list is empty");
    }
}

iterator begin() const {
    return ListIter<T>(_head);
}
iterator end() const {
    return ListIter<T>(_head->Prev());
}
bool empty() const noexcept {
    if (_head == NULL) {
        return true;
    }
    else {
        return false;
    }
}
size_t size() const noexcept {
    size_t counter = 0;
    if (empty()) {
        return 0;
    }
    else if (_head->Next() == _head->Prev()) {
        return 1;
    }
    else {
        Link<T> *last = _head->_next;
        while (last != _head) {
            last = last->_next;
            counter++;
        }
    }
    return counter;
}

iterator insert(const iterator& pos, const T& value) {
    if (empty()) {
        throw std::exception("list empty");
    }
    else {
        Node<T> prev = *pos->Prev();
        Node<T> newNode = new Node<T>(value, *pos, prev);
        prev->_next = newNode;
        *pos->_prev = newNode;
    }
}
ListIter erase(const iterator& pos) {
    Link<T> next = (*pos)->_next;
    Link<T> prev = (*pos)->_prev;
    next._prev = prev;
    prev._next = next;
    delete *pos;
}

void push_front(const T& value) {
    if (empty()) {
        _head = new Node<T>(value);
    }
    else if (size() == 1) {
        Node<T> *newHead = new Node<T>(value, _head, _head);
        _head->_next = newHead;
        _head->_prev = newHead;
        _head = newHead;
    }
    else {
        Node<T> *newhead = new Node<T>(value, _head, _head->Prev());
        _head = newhead;
    }
}

void push_back(const T& value) {
    if (empty()) {
        _head = new Node<T>(value);
    }
    else if (size() == 1) {
        Node<T> *last = new Node<T>(value, _head, _head);
        _head->_next = last;
        _head->_prev = last;
    }
    else {
        Link<T> *last = _head->Prev();
        Node<T> *newLast = new Node<T>(value, _head, last);
        last->_next = newLast;
    }
}

void pop_back() {
    if (empty()) {
        throw std::exception("list is empty");
    }
    else {
        Link<T> *last = _head->Prev();
        Link<T> *beforeLast = last->Prev();
        beforeLast->_next = _head;
        delete last;
    }
}


void pop_front() {
    if (empty()) {
        throw std::exception("list is empty");
    }
    else {
        Link<T> *newFront = _head->Next();
        Link<T> *temp = _head->Prev();
        temp->_next = newFront;
        delete _head;
        _head = static_cast<Node<T>*>(newFront);
    }
}



friend bool operator==(const List& lhs, const List& rhs) {
    bool result = true;
    if (lhs.size() == rhs.size()) {
        if (!lhs.empty()) {
            Node<T> *lhsNode = lhs._head;
            Node<T> *rhsNode = rhs._head;
            while (lhsNode->_next != NULL && rhsNode->Next() != NULL) {
                if (lhsNode->_data != rhsNode->_data) {
                    result = false;
                }
            }
        }
        else {
            throw std::exception("list empty");
        }


    }
    else {
        result = false;
    }
    return result;
}
friend std::ostream& operator<<(std::ostream& cout, const List& other);

void Check() const {
    /*assert(Invariant());*/
}

template< class T>
void swap(List<T>& lhs, List<T>& rhs) {
    Node<T> temp = rhs._head;
    rhs._head = lhs._head;
    lhs._head = temp;
}
private:
Node<T> *_head;

};

Мне просто нужно получить доступ к значению, которое должен дать разыменованный итератор.

1 Ответ

0 голосов
/ 20 декабря 2018

В insert и erase у вас есть const iterator& pos.Поскольку вы передаете по ссылке на константу, итератор равен const.Ваш operator* не помечен как const, поэтому вы не можете использовать его на постоянном объекте.Вам нужно либо предоставить const перегрузку, либо удалить const из параметра функции.

...