web-dev-qa-db-fra.com

C ++ remove_if sur un vecteur d'objets

J'ai un vecteur (l'ordre est important) d'objets (appelons-les classe myobj) où j'essaie de supprimer plusieurs objets à la fois.

class vectorList
{

    vector<*myobj> myList; 
};

class myobj
{

    char* myName;
    int index;
    bool m_bMarkedDelete;
}

Je pensais que la meilleure façon de procéder serait de marquer des objets myobj spécifiques pour suppression, puis d'appeler myList.remove_if () sur le vecteur. Cependant, je ne sais pas exactement comment utiliser les prédicats et autres pour cela. Dois-je créer une variable membre dans l'objet qui me permet de dire que je veux supprimer le myobj puis créer un prédicat qui vérifie si la variable membre a été définie?

Comment implémenter le prédicat en tant que partie de la classe vectorList?

30
Jordan

Dois-je créer une variable membre dans l'objet qui me permet de dire que je veux supprimer le myobj puis créer un prédicat qui vérifie si la variable membre a été définie?

Vous ne l'avez pas déjà fait? N'est-ce pas ce que m_bMarkedDelete est pour? Vous écririez le prédicat comme ceci:

bool IsMarkedToDelete(const myobj & o)
{
    return o.m_bMarkedDelete;
}

Alors:

myList.erase(
    std::remove_if(myList.begin(), myList.end(), IsMarkedToDelete),
    myList.end());

Ou, en utilisant des lambdas:

myList.erase(
    std::remove_if(myList.begin(), myList.end(),
        [](const myobj & o) { return o.m_bMarkedDelete; }),
    myList.end());

Si votre classe n'a pas réellement ce membre, et vous nous demandez si c'est le cas, alors je dirais non. Quels critères avez-vous utilisés pour décider de le marquer pour suppression? Utilisez ce même critère dans votre prédicat, par exemple:

bool IndexGreaterThanTen(const myobj & o)
{
    return o.index > 10;
}

note - Les fonctions que j'ai écrites sont bien sûr invalides car tous vos membres sont privés. Vous aurez donc besoin d'un moyen d'y accéder.

43
Benjamin Lindley

Un prédicat est essentiellement une comparaison conditionnelle. Il peut s'agir d'une fonction ou d'un objet. Voici un exemple utilisant de nouveaux lambdas C++. Ce code passera par le vecteur et supprimera les valeurs égales à 3.

int arg[6] = {1, 2, 3, 3, 3, 5};
std::vector<int> vec(arg, arg+6);
vec.erase(
   std::remove_if(
      vec.begin(), vec.end(),
      [](int i){ return i == 3;}),
   vec.end());

Edit: Pour les pointeurs, supposons que vous disposiez d'un vecteur ou d'interfaces que vous pouvez définir sur nullptr puis supprimez-les dans un lot avec à peu près le même code. Dans VS2008, vous n'aurez pas de lambdas, alors faites plutôt une fonction ou une structure de prédicat de comparaison.

bool ShouldDelete(IAbstractBase* i)
{
    return i == nullptr;
    // you can put whatever you want here like:
    // return i->m_bMarkedDelete;
}

std::vector<IAbstractBase*> vec;
vec.erase(
   std::remove_if(
      vec.begin(), vec.end(),
      ShouldDelete),
   vec.end());
10
AJG85