Я хочу использовать посетителя, которому назначена более сложная функция, которая должна вызывать изменения в контейнере, посетитель которого обладает только общими знаниями.
Пример сводится к минимуму. Настоящий посетитель имеет больше функций и совсем не обязательно обрабатывает контейнер.
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();
}
};
Для инициализации итератора я использую фиктивный вектор, который в этом случае я должен сохранить как член класса. Обычно я инициализирую итератор некоторым глобально недопустимым значением, таким как 0 для указателя.
К сожалению, 0 не является допустимым значением для итератора со многими компиляторами, а также кажется немного странным для использования. Есть ли более чистый способ выполнить то, что я пытаюсь, не прибегая к пустому пустому контейнеру?
Ответ
Вы не можете, нет никакого значения для стандартных итераторов, которые помещают их в «недопустимое состояние».
Предложенное решение
Вместо того, чтобы полагаться на ценность mLineIter
, инициализация по умолчанию mLineIter
и инициализировать mpLinesToSearch
в nullptr
в конструкторе.
Таким образом, вы будете теперь, когда mLineIter
не является действительным итератором, если mpLinesToSearch
все еще nullptr
,
ВЫПОЛНЕНИЕ ОБРАЗЦОВ
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();
}
};
( Заметка: Если вы компилируете свой источник как C ++ 03, nullptr
недоступен; если это так использовать NULL
или же 0
инициализировать ваш указатель)
если буст является опцией, вы можете использовать повышение :: опционально