Ответ 1
erase()
возвращает новый итератор:
for(iterator it = begin; it != end(container) /* !!! */;)
{
if (it->somecondition())
{
it = vec.erase(it); // Returns the new iterator to continue from.
}
else
{
++it;
}
}
Обратите внимание, что мы больше не можем сравнивать его с заранее рассчитанным концом, потому что мы можем его стереть и, следовательно, сделать его недействительным. Мы должны каждый раз получать конец.
Лучшим способом может быть объединение std::remove_if
и erase()
. Вы меняетесь от O (N 2) (каждый элемент стирается и сдвигается по мере продвижения) до O (N):
iterator it = std::remove_if(begin, end, pred);
vec.erase(it, vec.end());
Где pred
- ваш предикат удаления, например:
struct predicate // do choose a better name
{
bool operator()(const T& pX) const // replace T with your type
{
return pX.shouldIBeRemoved();
}
};
iterator it = std::remove_if(begin, end, predicate());
vec.erase(it, vec.end());
В вашем случае вы можете сделать его довольно общим:
class remove_by_caller
{
public:
remove_by_caller(AguiWidgetBase* pWidget) :
mWidget(pWidget)
{}
// if every thing that has getCaller has a base, use that instead
template <typename T> // for now a template
bool operator()(const T& pX) const
{
return pX.getCaller() == mWidget;
}
private:
AguiWidgetBase* mWidget;
};
std::vector<AguiTimedEvent>::iterator it =
std::remove_if(timedEvents.begin(), timedEvents.end(), remove_by_caller(widget));
timedEvents.erase(it, timedEvents.end());
Обратите внимание, что lambda существует, чтобы упростить этот процесс, как в Boost, так и в С++ 11.