IAE
IAE

Reputation: 2243

Erasing a container element using iterators

My current homework assignment has me creating an iterator class for a list. I'm stuck at creating a good erase(iterator where) function.

Current code (reduced to fit question):

class List
{
    class _Iter
    {
        friend class List;
    public:
        _Iter(ListElem *pCurr, List *pList);

        /* *, ->, ++, --, == and != operators overloaded */

    private:
        ListElem *pCurr_; List *pList_;
    };

    typedef _Iter iterator;

    iterator erase(iterator where);
};

with the erase being implemented like so:

// Precondition: List has been checked for size > 0.
List::iterator List::erase(List::iterator& where)
{
    // Erasing only element in list.
    if(where == end() && where == begin())
    {
        pop_back(); // or pop_front();
        return iterator(0, this);
    }

    // Elem at end
    if(where == end())
    {
        pop_back();
        return end();
    }
    else 
    {
        // Elem at beginning
        if(where == begin())
        {
            pop_front();
            return ++begin();
        }
    }

    // Elem somewhere between beginning and end.
    iterator temp(where);
    // The node next to pCurr_ should point to the one before pCurr_
    where.pCurr_->next->prev = where.pCurr_->prev;
    // The node before pCurr_ should point to the one after pCurr_
    where.pCurr_->prev->next = where.pCurr_->next;
    // Return the node after pCurr_
    ++temp;
    delete where.pCurr_;
    --size_;
    return temp;
} 

The first three cases- only element, element at end and element at beginning- are all okay. Coded fine and need absolutely no knowledge and private access to _Iters members. However, if the element is not in those positions, then I have (seemingly) no choice but to violate the encapsulation and change pCurr_ (element of the list) directly.

Is there any way to avoid this? I looked inside the STL list, but they used some other functions _Next_Node_(/* stuff */) and _Prev_Node_(/* stuff */) that weren't very useful to me. Google searches give me helpful results on how to use the erase function, not how to write it myself.

Question: Is there a way in which I can erase the element pointed to by my iterator without having to grab it's pCurr_ member?

Upvotes: 3

Views: 279

Answers (2)

visitor
visitor

Reputation: 8834

This is not really violating encapsulation. It is pretty much inevitable that a container and its iterators are tightly coupled. The two of them together hide the implementation details from the user. If they weren't friends to each other, more implementation details would have to be leaked to the user. The friend keyword can enhance encapsulation if the classes in question have valid reasons to know about each others internals.

Note that begin() == end() representing a list with one element is not the standard library convention where it means that the container is empty. end() should return an iterator to "one-past-the-end" of the container.

Upvotes: 2

CashCow
CashCow

Reputation: 31435

  1. Do not use identifiers beginning with underscore followed by an uppercase letter. They are reserved for standard library and system writers. Although you are writing your own list class, you are not actually writing the standard library.

  2. end() is normally one element past the end of the list, not the last element. (To get the actual last iterator of the list you can do l.rbegin().base() as it happens).

  3. Pass the iterator by value, not non-const reference.

  4. Why are you so concerned with modifying pCurr?

Upvotes: 3

Related Questions