2008-10-17 6 views
4

J'ai récemment rencontré un problème que je pensais boost :: lambda ou boost :: phoenix pourrait aider à résoudre, mais je n'ai pas pu obtenir la syntaxe droite et donc je l'ai fait d'une autre manière. Ce que je voulais faire était de supprimer tous les éléments dans les "chaînes" qui étaient inférieures à une certaine longueur et non dans un autre conteneur.Boost phoenix ou lambda problème de bibliothèque: suppression d'éléments d'un vecteur std ::

Ceci est mon premier essai:

std::vector<std::string> strings = getstrings(); 
std::set<std::string> others = getothers(); 
strings.erase(std::remove_if(strings.begin(), strings.end(), (_1.length() < 24 && others.find(_1) == others.end())), strings.end()); 

Comment j'ai fini par le faire était le suivant:

struct Discard 
{ 
    bool operator()(std::set<std::string> &cont, const std::string &s) 
    { 
     return cont.find(s) == cont.end() && s.length() < 24; 
    } 
}; 

lines.erase(std::remove_if(lines.begin(), lines.end(), boost::bind<bool>(Discard(), old_samples, _1)), lines.end()); 
+0

Dans votre « a fini par faire » extrait de code, il n'y a pas besoin de Bind Boost. Passez simplement l'ensemble (référence) au constructeur Discard. –

Répondre

3

Vous devez boost :: labmda :: bind aux appels de fonction lambda-ifier, pour par exemple la longueur 24 < partie devient:

bind(&string::length, _1) < 24 

EDIT

Voir la publication de "Head Geek" pour savoir pourquoi set :: find est difficile. Il l'a obtenu pour résoudre l'ensemble correct :: trouver la surcharge (donc j'ai copié cette partie), mais il a manqué un boost essentiel :: ref() - c'est pourquoi la comparaison avec end() a toujours échoué (le conteneur a été copié) .

int main() 
{ 
    vector<string> strings = getstrings(); 
    set<string> others = getothers(); 
    set<string>::const_iterator (set<string>::*findFn)(const std::string&) const = &set<string>::find; 
    strings.erase(
    remove_if(strings.begin(), strings.end(), 
     bind(&string::length, _1) < 24 && 
     bind(findFn, boost::ref(others), _1) == others.end() 
    ), strings.end()); 
    copy(strings.begin(), strings.end(), ostream_iterator<string>(cout, ", ")); 
    return 0; 
} 
+0

D'oh! Bien sûr ... merci pour l'indice, je vais ajouter ça au mien aussi. –

2

Le principal problème, autre que les appels bind (Adam Mitz était correcte sur cette partie), est que std::set<std::string>::find est une fonction surchargée, de sorte que vous ne pouvez pas spécifier directement dans l'appel bind. Vous devez dire au compilateur quifind à utiliser, comme ceci:

using namespace boost::lambda; 
typedef std::vector<std::string> T1; 
typedef std::set<std::string> T2; 

T1 strings = getstrings(); 
T2 others = getothers(); 

T2::const_iterator (T2::*findFn)(const std::string&) const=&T2::find; 
T2::const_iterator othersEnd=others.end(); 

strings.erase(std::remove_if(strings.begin(), strings.end(), 
    (bind(&std::string::length, _1) < 24 
     && bind(findFn, boost::ref(others), _1) == othersEnd)), 
    strings.end()); 

Cette compile, mais il ne fonctionne pas correctement, pour des raisons que je ne l'ai pas encore compris ... la fonction est find ne retourne jamais others.end(), donc il ne supprime jamais rien. Je travaille encore sur cette partie.

EDIT: Correction, la fonction findest retour others.end(), mais la comparaison ne reconnaît pas lui. Je ne sais pas pourquoi. Après le commentaire d'Adam, je vois ce qui ne va pas, et j'ai corrigé le problème. Cela fonctionne maintenant comme prévu.

(Regardez l'historique des modifications si vous voulez voir mon programme de test complet.)

+0

C'est toujours un ref ou un var ... –

Questions connexes