1

I'm implementing a custom container with an STL-like interface for a 3D grid control for my scientific software. This is my second question regarding the iterator class for this container. Thanks for helping me with the first!

My question is just like "How do you avoid code duplication when implementing const and non-const iterators?". I just wanted to ask if it is possible to provide a template-less solution? (And without providing a second const iterator class!)

The iterator class looks like this:


class spGridIterator {
public:
    typedef forward_iterator_tag iterator_category;
    typedef spGridNode value_type;
    typedef int difference_type;
    typedef spGridNode* pointer;
    typedef spGridNode& reference;

    spGridIterator();
    spGridIterator(spGrid* gr, int index);
    spGridIterator(const spGridIterator& orig);
    virtual ~spGridIterator();

    // STL-ные операторы итератора
    bool operator == ( const spGridIterator& hs ) const {
        return (m_grid == hs.m_grid) && (m_idx == hs.m_idx);
    }

    bool operator != ( const spGridIterator& hs ) const {
        return (m_grid != hs.m_grid) || (m_idx != hs.m_idx);
    }

    // non-const operators
    spGridIterator& operator++();
    spGridIterator& operator++(int);

    reference operator*() const;
    pointer operator->() const { return &(operator*()); }

private:
    spGrid* m_grid;
    int m_idx;
};

And an implementation...

spGridIterator::spGridIterator(spGrid* gr, int index) {
    m_grid = gr;
    m_idx  = index;
}

spGridIterator& spGridIterator::operator++()
{
    int last = m_grid->numpoints;

    if (m_idx < last) {
        m_idx++;
    }
    return *this;
}

spGridIterator& spGridIterator::operator++(int) {
    return operator++();
}

spGridIterator::reference spGridIterator::operator*() const {
    return ( m_grid->GetNode(m_idx) );
}

I checked the doctor dobbs article about custom iterator implementation. They suggest implementing an iterator class template and adding an additional template parameter for the value_type.

Well, the second solution is to provide a regular iterator and a const iterator classes.

Is there third, maybe "kinda hacky", single class template-less solution? Maybe providing a conversion operator or an additional const version of operator++()?

Thanks, Ilya

4
  • Your operator++(int) returns the wrong value - it's postfix ++, so it should return a copy of the iterator prior to being incremented, not a reference to the iterator after being iterated. Canonical implementation is Iterator Iterator::operator++(int) { Iterator old = *this; ++(*this); return old; } Commented Oct 31, 2010 at 18:35
  • I've got it! Thanks for a valuable comment!
    – ezpresso
    Commented Oct 31, 2010 at 18:56
  • I not really needed I would not implement the postfix ++ operator. You really want to encourage people using the prefix ++ operator instead of the postfix ++ operator.
    – Patrick
    Commented Oct 31, 2010 at 19:44
  • 1
    @Patrick: good idea, but if it doesn't have postfix ++ then it isn't an iterator, according to the standard. Commented Nov 1, 2010 at 13:29

1 Answer 1

3

If you want to go kind of hacky, you may be able to abuse "const_cast" to create a const iterator out of a non-const one.

1
  • Simple trick, but it works. Don't forget to clearly comment in the source code why you are abusing the const_cast. Otherwise, the next developer reading the code will think that you made a mistake and will want to correct your error, euh trick.
    – Patrick
    Commented Oct 31, 2010 at 19:43

Not the answer you're looking for? Browse other questions tagged or ask your own question.