tags:

views:

7252

answers:

6

I'm trying to learn C++ so forgive me if this question demonstrates a lack of basic knowledge, you see, the fact is, I have a lack of basic knowledge.

I want some help working out how to create an iterator for a class I have created.

I have a class 'Shape' which has a container of Points. I have a class 'Piece' which references a Shape and defines a position for the Shape. Piece does not have a Shape it just references a Shape.

I want it to seem like Piece is a container of Points which are the same as those of the Shape it references but with the offset of the Piece's position added.

I want to be able to iterate through the Piece's Points just as if Piece was a container itself. I've done a little reading around and haven't found anything which has helped me. I would be very grateful for any pointers.

Cheers

+3  A: 

/EDIT: I see, an own iterator is actually necessary here (I misread the question first). Still, I'm letting the code below stand because it can be useful in similar circumstances.


Is an own iterator actually necessary here? Perhaps it's sufficient to forward all required definitions to the container holding the actual Points:

// Your class `Piece`
class Piece {
private:
    Shape m_shape;

public:

    typedef std::vector<Point>::iterator iterator;
    typedef std::vector<Point>::const_iterator const_iterator;

    iterator begin() { return m_shape.container.begin(); }

    const_iterator begin() const { return m_shape.container.begin(); }

    iterator end() { return m_shape.container.end(); }

    const_iterator end() const { return m_shape.const_container.end(); }
}

This is assuming you're using a vector internally but the type can easily be adapted.

Konrad Rudolph
perhaps he wants to use the STL algorithm or functional features against his class...
gbjbaanb
The original question does actually say that the iterator of the piece container should modify the values when returning them. That would require a separate iterator, although it should probably be inherited or otherwise obtained mostly from the original.
workmad3
@gbjbaanb: The good thing about my code is that it *can* be used by STL algorithms.
Konrad Rudolph
Yes, it even works with BOOST_FOREACH
anno
+2  A: 

The solution to your problem is not the creation of your own iterators, but the use of existing STL containers and iterators. Store the points in each shape in a container like vector.

class Shape {
    private:
    vector <Point> points;

What you do from then on depends on your design. The best approach is to iterate through points in methods inside Shape.

for (vector <Point>::iterator i = points.begin(); i != points.end(); ++i)
    /* ... */

If you need to access points outside Shape (this could be a mark of a deficient design) you can create in Shape methods that will return the iterator access functions for points (in that case also create a public typedef for the points container). Look at the answer by Konrad Rudolph for details of this approach.

Diomidis Spinellis
He'll still need to make his own iterator that forwards requests to Piece to the Shapes that are in that Piece. Custom iterators are a great tool here, and very elegant to use.
Roel
+6  A: 

Take a look here or google for "implement custom iterator" which returns a lot of in-depth results (eg this ddj article)

Basically, inherit from std::iterator to get most of the work done for you.

gbjbaanb
A: 
Augusto Radtke
This is exactly the same what the STL does except that you use a different syntax and concept assumptions. Why would you inflict that on programmers who have to maintain your code? If everybody would just stick to the simple STL way and not invite their own wheel, maintenance would be much easier...
Roel
I don't inflict anything, this code came from something that never will be open source. I showed the way I do it, if you don't like it, don't use it, the same way I don't use STL. But I've been carefully polite to not vote different approaches down.
Augusto Radtke
This is different from STL, keeps the code with less assemblies. And this is a perfect for a beginner that is willing to learn C++ and understand how iterators works. And it is what the OP asked, his own itarators. Thanks Augusto Radtke, your answer was very helpful for me.
BrunoLM
+9  A: 

You should use Boost.Iterators. It contains a number of templates and concepts to implement new iterators and adapters for existing iterators. I have written an article for one of the ACCU's magazines about this very topic; it's in the December 2008 issue, available online on http://accu.org/index.php/journals/c247/. It discusses an (IMO) elegant solution for exactly your problem: exposing member collections from an object, using Boost.Iterators.

If you want to use the stl only, the Josuttis book has a chapter on implementing your own STL iterators (http://www.josuttis.com/libbook/).

Roel
+1  A: 

Here Designing a STL like Custom Container is an excellent article which explains some of the basic concepts of how an STL like container class can be designed along with the iterator class for it. Reverse iterator (little tougher) though is left as an exercise :-)

HTH,

Abhay