How to initialize an iterator to something invalid if the container is not known?

c++, containers, visitor-pattern

Solution

The answer

You can't, there is no value for standard iterators that puts them into an "invalid state".

Proposed solution

Instead of relying on the value of `mLineIter`, default-initialize `mLineIter` and initialize `mpLinesToSearch` to `nullptr` in the constructor.

This way you will now that `mLineIter` isn't a valid iterator if `mpLinesToSearch` is still `nullptr`.

SAMPLE IMPLEMENTATION

class OverlapDisabler: public IntersectionHandler{
private:
  std::vector<Segment>* mpLinesToSearch;
  std::vector<Segment>::iterator mLineIter;

public:
  InsideCollector() : mpLinesToSearch (nullptr), mLineIter() { }

  ...

  void advance(){
    if (mpLinesToSearch == nullptr)
      return; // no iterator to increment

    if(mLineIter != mpLinesToSearch->end()) ++mLineIter;
  }

 ...     

  void treatIntersection(){
    if(mpLinesToSearch == nullptr)
      return; // the iterator doesn't refer to any element

    if(mLineIter != mpLinesToSearch->end()) mLineIter->disable();
  }    
};

( Note: If you are compiling your source as C++03, `nullptr` isn't available; if that is the case use `NULL` or `0` to initialize your pointer )

Problem

I want to use a visitor given to a more complex function which should inflict changes on a container via the visitor of which is has only general knowledge. The example is reduced to a minimum. The real visitor has more functions and does not necessarily handle a container at all. ``` class IntersectionHandler{ public: virtual void advance()=0; virtual void treatIntersection()=0; }; class OverlapDisabler: public IntersectionHandler{ private: std::vector<Segment> mEmpty; std::vector<Segment>* mpLinesToSearch; std::vector<Segment>::iterator mLineIter; public: InsideCollector():mEmpty(),mpLinesToSearch(&mEmpty),mLineIter(mEmpty.end(){} void setLineContainer(std::vector<Segment>* lines){ mpLinesToSearch = lines; mLineIter = mpLinesToSearch->begin(); } void advance(){ if(mLineIter != mpLinesToSearch->end()) ++mLineIter; } void treatIntersection(){ if(mLineIter != mpLinesToSearch->end()) mLineIter->disable(); } }; ``` To intitailize the iterator I use a dummy vector, that I must keep as a class member in this case. Usually I would initialise the iterator with some globally invalid value such as 0 for a pointer. Unfortunately 0 is not a valid value for an iterator with many compilers and also seems a little odd to use. Is there a cleaner way to accomplish what I am trying without resorting to an empty dummy container?

Original source