2008-11-03 18 views
17

Quiero encontrar en un vector de punteros de objeto para un objeto coincidente. He aquí un código de ejemplo para ilustrar mi problema:Cómo usar el algoritmo de búsqueda con un vector de punteros a objetos en C++?

class A { 
public: 
    A(string a):_a(a) {} 
    bool operator==(const A& p) { 
     return p._a == _a; 
    } 

private: 
    string _a; 
}; 

vector<A*> va; 

va.push_back(new A("one")); 
va.push_back(new A("two")); 
va.push_back(new A("three")); 

find(va.begin(), va.end(), new A("two")); 

Quiero encontrar el segundo elemento empujado en el vector. Pero dado que vector se define como una colección de punteros, C++ no utiliza mi operador sobrecargado, sino que usa una comparación de puntero implícita. ¿Cuál es la forma preferida de solución de C++ en esta situación?

Respuesta

17

Uso find_if con un funtor:

template <typename T> 
struct pointer_values_equal 
{ 
    const T* to_find; 

    bool operator()(const T* other) const 
    { 
     return *to_find == *other; 
    } 
}; 


// usage: 
void test(const vector<A*>& va) 
{ 
    A* to_find = new A("two"); 
    pointer_values_equal<A> eq = { to_find }; 
    find_if(va.begin(), va.end(), eq); 
    // don't forget to delete A! 
} 

Nota: el operador == para A debe ser constante, o, mejor aún, escribir como una función friend no miembro.

+0

Creo que debe ser find_if en el código? – esrkan

+0

De hecho, solo puede std :: find() un predicado en un contenedor de predicados. – MSalters

+0

james puede agregar más explicaciones sobre esta línea pointer_values_equal eq = {to_find}; – yesraaj

4

O use std :: find_if y proporcione un predicado adecuado usted mismo, consulte otras respuestas para ver un ejemplo de esto.

O como alternativa echar un vistazo a boost::ptr_vector, que proporciona acceso de referencia transparente a los elementos que realmente están almacenadas como punteros (como un bono extra, la gestión de memoria se maneja para usted también)

1

También es posible usar boost :: lambda:

using namespace boost::lambda; 
find_if(va.begin(), va.end(), *_1 == A("two")); 

Por supuesto, se debe preferir el uso shared_ptrs por lo que no tiene que acordarse de eliminar!

Cuestiones relacionadas