If I want to expose an iterator to a class member container, I can do so like this:

class PatchCollection
  // Iterator interface
  typedef std::set<Patch>::iterator iterator;
  typedef std::set<Patch>::const_iterator const_iterator;

  iterator begin() { return SourcePatches.begin(); }

  iterator end() { return SourcePatches.end(); }


  std::set<Patch> Patches;

However, if the member has to be a std::set<Patch*>, but I want the class's iterator to act like it is iterating over a set::<Patch> instead, what would I have to do?



Recommended Answers

Okay. In this case, an indirect_iterator is exactly what you need.

Jump to Post

All 4 Replies

I want to sort the container of pointers to const objects via an indirect_iterator: http://ideone.com/r5qBu - is this not possible (for the same reason that storing const objects in the vector directly is not possible - that the assignment operator doesn't make sense)?

The main problem, of course, with the code you posted is that the indirect_iterator class implements the assignment operator in terms of an assignment operation on the pointees, not the pointers. Because indirect_iterator was made with the assumption that it should behave exactly as if the iterator was an ordinary iterator in a container of values (not pointers), it has to implement assignment with deep copies. Evidently, if your pointees are const objects, then you cannot do any operation that would require the iterator's value-type to be non-const.

What you would need is a sort of hybrid indirect-iterator that would dereference the pointers for all "value-access" operations, and that would move the smart-pointers around whenever doing move / copy / assignment operations. The problem is that these are not distinguishable because they both go through the same operator, the dereference operator on the indirect_iterator class. For instance, the standard sort algorithm is most likely based on a swap operation like swap(*it1, *it2) which is a data-move operator that relies on the dereference operator of the iterator, then, it probably also calls compare(*it1, *it2) which is a data-access operation, but from the point-of-view of the implementer of the iterator class, these two operations cannot be distinguished at all.

The only way to solve this is to use an indirect compare operation and a normal iterator (to the pointers) for the sort operation. For other operations in which you want to have an indirect-iterator, just use make_indirect_iterator from outside your MyCollection class (or provide alternative begin() and end() functions). Or you can also make an indirect-container adaptor (which was proposed to boost some years ago, I'm not sure if it is in there somewhere, but it is pretty easy to conjure up by hand too).

commented: Thanks for the thorough analysis. +12
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, learning, and sharing knowledge.