marcoo
marcoo

Reputation: 869

Custom iterator

I am making a library using the data structure: std::vector<std::string>. I have to satisfy the API, which says that in order to iterate through my data structure users would have to do the following:

for (lib::result::const_iterator it = data.begin(); it != data.end(); it++)

There are two ways I could do this, implement lib::result::const_iterator on my own or inherit from std::vector<std::string>::iterator, they should both work. I have read that inheriting from the vector iterator is a bad idea.

I have decided to use Boost iterator facade, is this a good idea? Also, I am having trouble implementing increment(). If I have a pointer to a string in an std::vector, how do I point to the next string?

Lastly, my implementation could change from std::vector<std::string>, to std::vector<MyDatatype>, so I would like to use the boost facade so if ever I decide to make changes to my data structure, things would be easier. Thanks.

Upvotes: 1

Views: 511

Answers (2)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275220

namespace lib {
  struct class {
    typedef std::vector<std::string>::const_iterator const_iterator;
    const_iterator begin() const;
    const_iterator end() const;
  };
};

If you change the underlying type, assuming that the iterator is compatible with the std::vector<std::string> iterator, just change the typedef. If it isn't compatible with the std::vector<std::string> iterator, you are breaking your API. However, this really is a problem for another day.

If you do need to implement an iterator, boost's "iterator adaptor" is a good choice: wrap the std::vector<std::string> iterator with yours.

"iterator fascade" would be something I might use if I had to generate a stable binary interface over library version changes. In that case, my "iterator facade" would forward to a pImpl-type virtual interface (which repeats the methods that "iterator facade" requires from its implementation) that implemented each feature of the facade. The internal pImpl implementation would then forward the methods to the std::vector<std::string> in a way similar to how "iterator adaptor" works. But in almost all cases, this is overkill.

But the first case -- where you typedef std::vector<std::string>::const_iterator -- is both the most efficient and easiest to implement.

Upvotes: 1

Loki Astari
Loki Astari

Reputation: 264331

You can just use the vectors iterator:

class MyClass
{
     typedef std::vector<std::string>  MyData;

     MyData    data;

     public:
         typedef  MyData::iterator       iterator;
         typedef  MyData::const_iterator const_iterator;

         iterator       begin()       {return data.begin();}
         const_iterator begin() const {return data.begin();}

         .... etc

Upvotes: 2

Related Questions