2010-08-08 5 views
5

En ce moment, j'ai ce code:simplifier le code C++ simple - quelque chose comme Pythons toute

bool isAnyTrue() { 
    for(std::list< boost::shared_ptr<Foo> >::iterator i = mylist.begin(); i != mylist.end(); ++i) { 
     if((*i)->isTrue()) 
      return true; 
    } 

    return false; 
} 

Je l'ai utilisé Boost ici et là, mais je ne me souvenais vraiment une façon simple d'écrire un peu comme Je peut l'écrire en Python, par exemple:

def isAnyTrue(): 
    return any(o.isTrue() for o in mylist) 

y at-il construit en STL/Boost pour l'écrire plus ou moins comme ça?

Ou peut-être un équivalent à ce code Python:

def isAnyTrue(): 
    return any(map(mylist, lambda o: o.isTrue())) 

Je suis Surtout demandais s'il y a une any existante (et all) équivalente encore Boost/STL. Ou pourquoi pas (parce que cela me semble assez utile et je l'utilise assez souvent en Python).

Répondre

6

C++ n'a pas (encore) de construction foreach. Vous devez écrire vous-même/

Cela dit, vous pouvez utiliser l'algorithme std::find_if ici:

bool isAnyTrue() 
{ 
    return std::find_if(mylist.begin(), mylist.end(), std::mem_fun(&Foo::isTrue)) 
      != mylist.end(); 
} 

En outre, vous devriez probablement utiliser std::vector ou std::deque plutôt que std::list.

EDIT: STH vient de me que ce ne compilera pas réellement parce que votre liste contient shared_ptr au lieu des objets réels ... à cause de cela, vous allez avoir besoin d'écrire votre propre foncteur, ou compter sur boost:

//#include <boost/ptr_container/indirect_fun.hpp> 

bool isAnyTrue() 
{ 
    return std::find_if(mylist.begin(), mylist.end(), 
      boost::make_indirect_fun(std::mem_fun(&Foo::isTrue))) != mylist.end(); 
} 

Remarque, je n'ai pas testé cette deuxième solution.

+0

@sth: Comment est cette solution? –

+0

Boost a une foreach ('BOOST_FOREACH'). – Albert

+0

@Albert: Oui, c'est le cas. Mais même dans ce cas, vous devriez préférer les appels d'algorithme aux boucles explicites. –

4

Au lieu de find_if j'irais avec un personnalisé. Je l'aime mieux en termes de lisibilité sur find_if mais c'est une question de goût.

template<class ForwardIterator, class Pred> 
bool any(ForwardIterator begin, ForwardIterator end, Pred pred) { 
    for(; begin != end; ++begin) 
    if(pred(*begin)) return true; 

    return false; 

    //or 
    //return std::find_if(mylist.begin(), mylist.end(), std::mem_fun(&Foo::isTrue)) 
    //  != mylist.end(); 

} 

bool isAnyTrue() { 
    return any(mylist.begin(), mylist.end(), std::mem_fun(&Foo::isTrue)); 
} 

Editer: Alternative avec find_if par Billy ONeal.

+1

Rien de mal avec un custom, mais pourquoi ne pas l'implémenter en termes de 'find_if'? –

+0

Ok, eh bien, je me demandais surtout pourquoi il n'y a pas de 'any' (ou quelque chose de similaire) dans Boost pour le moment. C'est presque comme si je l'avais déjà fait (pas dans ma question mais dans mon vrai code), avec une fonction 'any' personnalisée. – Albert

+0

@Albert - La chose sympa à propos de cette version de any() est qu'il utilise des modèles, et fonctionne avec (sans jeu de mots) tout type. C'est quelque chose que vous pouvez mettre dans votre boîte à outils de programmation et utiliser n'importe où. –

4

La nouvelle norme C++ a std :: any_of, par ex.

bool isAnyTrue() 
{ 
    return std::any_of(mylist.begin(), mylist.end(), std::mem_fn(&Foo::isTrue)); // Note std::mem_fn and not std::mem_fun 
} 

VS2010 l'a implémenté.

+1

g ++ 4.4 implémente cela aussi. – rafak

+0

& rafak: S'il vous plaît fournir des liens! –

+0

Premier résultat dans google. http://msdn.microsoft.com/en-us/library/ee396393.aspx – ronag

Questions connexes