2010-08-08 27 views
5

Teraz mam ten kod:uprościć prostego kodu C++ - coś jak pyton dowolny

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

    return false; 
} 

Użyłem Boost, tu i potem, ale nie mogłem sobie przypomnieć żadnej prosty sposób napisać to trochę jak Może napisałbym to w Pythonie, np .:

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

Czy istnieje jakaś konstrukcja w STL/Boost, aby napisać ją mniej więcej tak?

Albo odpowiednik tego kodu Pythona:

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

Głównie Zastanawiam się, czy istnieje jakikolwiek istniejący any (i all) równowartość w Boost/STL jeszcze. Lub dlaczego tak nie jest (ponieważ wydaje się całkiem przydatny i często go używam w Pythonie).

Odpowiedz

6

C++ nie ma (jeszcze) konstrukcji foreach. Trzeba napisać, że sam/

Mimo to, można użyć algorytmu std::find_if tutaj:

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

Ponadto, powinny prawdopodobnie być używając std::vector lub std::deque zamiast std::list.

EDIT: sth właśnie poinformował mnie, że nie będzie to faktycznie kompilacji, ponieważ lista zawiera shared_ptr zamiast rzeczywistych obiektów ... powodu, że masz zamiar trzeba napisać własną funktor, lub polegać na 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(); 
} 

Uwaga, nie testowałem tego drugiego rozwiązania.

+0

@sth: Jak to rozwiązanie? –

+0

Zwiększenie ma foreach ('BOOST_FOREACH'). – Albert

+0

@Albert: Tak, tak. Ale nawet w takim przypadku powinieneś preferować wywołania algorytmów do jawnych pętli. –

4

Zamiast find_if użyłbym dowolnego niestandardowego. Podoba mi się lepiej pod względem czytelności w stosunku do find_if, ale to kwestia gustu.

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)); 
} 

Edytuj: Alternatywne dowolne z find_if od Billy ONeal.

+1

Nic nie jest w porządku z niestandardowym, ale dlaczego nie zaimplementować go pod kątem 'find_if'? –

+0

Ok, cóż, zastanawiałem się głównie dlaczego nie ma takiego "any" (lub czegoś podobnego) w Boost jeszcze. Jest to głównie tak, jak zrobiłem to już (nie w moim pytaniu, ale w moim prawdziwym kodzie), z niestandardową własną funkcją "any". – Albert

+0

@Albert - Fajną rzeczą w tej wersji jakiejkolwiek() jest to, że używa szablonów i działa z (żadnym kalamburem) dowolnym typem. Jest to coś, co można znaleźć w zestawie narzędzi do programowania i używać go w dowolnym miejscu. –

4

Nowy standard C++ ma std :: any_of, np.

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 ma to zaimplementowane.

+1

g ++ 4.4 implementuje to również. – rafak

+0

& rafak: Podaj linki! –

+0

Pierwszy wynik w google. http://msdn.microsoft.com/en-us/library/ee396393.aspx – ronag