sort libreria for_each cstdlib algorithms algorithm stl c++

algorithm - libreria - std for_each c++



¿Cómo puedo negar un functor en C++(STL)? (4)

A medida que lo usa, no necesita el functor FindPredicate, ya que en el ejemplo solo está probando la igualdad.

bool all_equal(std::vector<SomeType>& v, SomeType& valueToFind) { return v.end() == find_if(v.begin(), v.end(), std::bind1st (equal_to (), valueToFind) ); } bool all_not_equal( std::vector<SomeType>& v, SomeType &valueToFind ) { { return v.end() == find_if(v.begin(), v.end(), std::bind1st (not_equal_to (), valueToFind) ); }

Y podrías hacer de esto una plantilla en sí misma.

template< typename InputIterator , typename Predicate > bool test_all( InputIterator first, InputIterator last, Predicate pred ) { return last == find_if( first, last, pred ); } test_all( v.begin(), v.end(), std::bind1st( not_equals_to_( value )) );

Tengo alguna función para encontrar un valor:

struct FindPredicate { FindPredicate(const SomeType& t) : _t(t) { } bool operator()(SomeType& t) { return t == _t; } private: const SomeType& _t; }; bool ContainsValue(std::vector<SomeType>& v, SomeType& valueToFind) { return find_if(v.begin(), v.end(), FindPredicate(valueToFind)) != v.end(); }

Ahora me gustaría escribir una función que compruebe si todos los miembros de un vector satisfacen ese predicado:

bool AllSatisfy(std::vector<SomeType>& v) { /* ... */ }

Una solución es usar el algoritmo std::count_if .

¿Alguien sabe una solución que implica negar el predicado?


Consulte el func. Biblioteca de std not1 , devuelve un functor que es lógico, no de lo que devuelva el functor que le proporcione.

Debería poder hacer algo como:

bool AllSatisfy(std::vector<SomeType>& v, SomeType& valueToFind) { return find_if(v.begin(), v.end(), not1(FindPredicate(valueToFind))) != v.end(); }


La mejor solución es usar la biblioteca funcional STL . Al derivar su predicado de la función unary_function<SomeType, bool> , entonces podrá usar la función not1 , que hace exactamente lo que necesita (es decir, negando un predicado unario).

Aquí es cómo puedes hacer eso:

struct FindPredicate : public unary_function<SomeType, bool> { FindPredicate(const SomeType& t) : _t(t) {} bool operator()(const SomeType& t) const { return t == _t; } private: const SomeType& _t; }; bool AllSatisfy(std::vector<SomeType>& v, SomeType& valueToFind) { return find_if(v.begin(), v.end(), not1(FindPredicate(valueToFind))) == v.end(); }

Si desea lanzar su propia solución (que es, en mi humilde opinión, no es la mejor opción ...), bien, podría escribir otro predicado que sea la negación del primero:

struct NotFindPredicate { NotFindPredicate(const SomeType& t) : _t(t) { } bool operator()(SomeType& t) { return t != _t; } private: const SomeType& _t; }; bool AllSatisfy(std::vector<SomeType>& v) { return find_if(v.begin(), v.end(), NotFindPredicate(valueToFind)) == v.end(); }

O podría hacerlo mejor y escribir una plantilla de factor de negor, como:

template <class Functor> struct Not { Not(Functor & f) : func(f) {} template <typename ArgType> bool operator()(ArgType & arg) { return ! func(arg); } private: Functor & func; };

que podrías usar como sigue:

bool AllSatisfy(std::vector<SomeType>& v, SomeType& valueToFind) { FindPredicate f(valueToFind); return find_if(v.begin(), v.end(), Not<FindPredicate>(f)) == v.end(); }

Por supuesto, la última solución es mejor porque puede reutilizar la estructura No con cada functor que desee.


La primera vez que usé not1 me pregunté por qué no se llamaba simplemente not .

La respuesta me sorprendió un poco (ver comentario).