2010-08-08 19 views
5

En este momento, tengo este código:simplificar C++ código sencillo - algo así como pitones cualquier

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

    return false; 
} 

he utilizado Boost aquí y entonces, pero realmente no podía recordar ninguna forma sencilla de escribir algo así como yo tal vez escribo en Python, por ejemplo:

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

¿hay alguna construcción en STL/Boost para escribir más o menos así?

O tal vez un equivalente a este código Python:

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

Sobre todo me gustaría saber si hay alguna existente any (y all) equivalente en Boost/STL todavía. O por qué no (porque parece bastante útil y lo uso con bastante frecuencia en Python).

Respuesta

6

C++ no tiene (todavía) una construcción foreach. Tienes que escribir que usted mismo/

Dicho esto, se puede utilizar el algoritmo std::find_if aquí:

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

Además, es probable que debe utilizar std::vector o std::deque en lugar de std::list.

EDIT: algo me acaba de informar de que esta realidad no va a compilar debido a que su lista contiene shared_ptr en lugar de los objetos reales ... por eso, vas a tener que escribir su propia funtor, o confíe en el impulso:

//#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(); 
} 

Nota: No he probado esta segunda solución.

+0

@sth: ¿Cómo es esta solución? –

+0

Boost tiene un foreach ('BOOST_FOREACH'). – Albert

+0

@Albert: Sí, lo hace. Pero incluso en ese caso, debería preferir las llamadas de algoritmo a los bucles explícitos. –

4

En lugar de find_if iría con una personalizada. Me gusta más en términos de legibilidad que en find_if, pero esa es una cuestión de gusto.

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

Editar: Alternativa cualquiera con find_if por Billy ONeal.

+1

No hay nada malo con una costumbre, pero ¿por qué no implementarla en términos de 'find_if'? –

+0

Ok, bueno, me preguntaba en su mayoría por qué todavía no hay 'any' (o algo similar) en Boost. Esto es principalmente como lo he hecho ya (no en mi pregunta, sino en mi código real), con una función personalizada de 'any'. – Albert

+0

@Albert - Lo bueno de esta versión de any() es que usa plantillas, y funciona con (sin juego de palabras) cualquier tipo. Es algo que puedes rellenar en tu juego de herramientas de programación y usar en cualquier lugar. –

4

El nuevo estándar C++ tiene std :: any_of, p.

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 ha implementado esto.

+1

g ++ 4.4 implementa esto también. – rafak

+0

& rafak: ¡proporcione enlaces! –

+0

Primer resultado en google. http://msdn.microsoft.com/en-us/library/ee396393.aspx – ronag

Cuestiones relacionadas