2011-08-04 11 views
24

Tengo una clase que representa un usuario llamado Nick y quiero usar std::find_if en ella, donde quiero encontrar si el vector de la lista de usuarios tiene un objeto incluido con el mismo nombre de usuario que paso. Intenté algunos intentos intentando crear Nick un nuevo objeto para el nombre de usuario que quiero probar y sobrecargar el == operator y luego tratar de utilizar find/find_if en el objeto:Cómo usar std :: find/std :: find_if con un vector de objetos de clase personalizados?

std::vector<Nick> userlist; 
    std::string username = "Nicholas"; 

if (std::find(userlist.begin(), userlist.end(), new Nick(username, false)) != userlist.end())) { 
    std::cout << "found"; 
} 

he sobrecargado el == operator por lo comparando Nick == nick2 debería funcionar, pero la función devuelve error C2678: binary '==' : no operator found which takes a left-hand operand of type 'Nick' (or there is no acceptable conversion).

Aquí es mi clase de Nick como referencia:

class Nick { 
private: 
    Nick() { 
     username = interest = email = ""; 
        is_op = false; 
    }; 
public: 
    std::string username; 
    std::string interest; 
    std::string email; 
    bool is_op; 

    Nick(std::string d_username, std::string d_interest, std::string d_email, bool d_is_op) { 
     Nick(); 
     username = d_username; 
     interest = d_interest; 
     email = d_email; 
     is_op = d_is_op; 
    }; 
    Nick(std::string d_username, bool d_is_op) { 
     Nick(); 
     username = d_username; 
     is_op = d_is_op; 
    }; 
    friend bool operator== (Nick &n1, Nick &n2) { 
     return (n1.username == n2.username); 
    }; 
    friend bool operator!= (Nick &n1, Nick &n2) { 
     return !(n1 == n2); 
    }; 
}; 

Respuesta

14

Tiene que definir operator == con dos objetos fuera de su clase, como una función de herramienta, no como un miembro.

Luego, para hacerlo amigo, simplemente ponga la declaración de la función dentro de la clase.

intentar algo como esto:

class Nick { 

public: 
    friend bool operator== (const Nick &n1, const Nick &n2); 
}; 


bool operator== (const Nick &n1, const Nick &n2) 
{ 
     return n1.username == n2.username; 
} 

También su hallazgo debería tener este aspecto:

std::find(userlist.begin(), userlist.end(), Nick(username, false)); 

No hay necesidad de "nueva".

+0

En realidad, en lugar de definir una función de amigo, debería usar la función de miembro bool operator == (const Nick & a). –

+1

Tiene la opción, pero hay muchos programadores a los que les gusta evitar miembro si no es necesario y tener operador como == como funciones externas de amigo libre. Creo que también es el caso de las implementaciones de la biblioteca estándar. – Nikko

+0

Acabo de intentar como sugirió. ¿No debería la respuesta ser así: 'std :: find (userlist.begin(), userlist.end(), y Nick (username, false));'? – Marschal

3

usted está pasando un puntero a la función de búsqueda. La caída de la nueva:

std::find(userlist.begin(), userlist.end(), Nick(username, false)) 

Además, los operadores deben aceptar sus argumentos por referencia constante, cuando no se modifiquen ellos.

bool operator== (const Nick &n1, const Nick &n2) 
0

Usted puede usar boost :: bind

std::find_if(userlist.begin(), userlist.end(), 
      boost::bind(& Nick::isFound, 
         _1)); 

acaba de poner en práctica bool Nick :: isFound()

También se puede pasar los criterios

std::find_if(userlist.begin(), userlist.end(), 
       boost::bind(& Nick::compare, 
          _1, 
          nick)); 

implemento

bool Nick::compare(const Nick & nick) 
{ 
    return this->username == nick.username; 
} 
1

estoy notando que está intentando llamar a un constructor de otro de esta manera:

Nick(std::string d_username, bool d_is_op) { 
     Nick(); 
... 

Bueno, lo siento, pero esto no funciona. La línea Nick() solo crea un temporal y no afecta a this. El reenvío del constructor solo es posible en C++ 0x (el próximo estándar)

En cuanto a su problema, esta pregunta hecha hace un par de días acerca de binary_search cubre los mismos motivos. La mejor respuesta es simplemente increíble.

Mystical restriction on std::binary_search

HTH.

P.S. Idealmente esto debería haber sido un comentario, pero es demasiado detallado

36

Si está utilizando C++ 0X se puede utilizar una expresión lambda sencilla

std::string username = "Nicholas";  
std::find_if(userlist.begin(), userlist.end(), [username](Nick const& n){ 
    return n.username == username; 
}) 
+7

él no dice que está usando C++ 0X ... – Nikko

+13

@Nikko él tampoco dice que no lo es. Por lo tanto, la palabra "si" al comienzo de esta respuesta. –

+0

Sí, todo esto tuvo algún sentido en 2011 y tal vez hubo una edición después de mi comentario ... – Nikko

9

Sé que usted quiere sobrecargar el operador ==, pero lo mismo se puede hacer fácilmente con un predicado:

struct UsernameIs { 
    UsernameIs(string s) : toFind(s) { } 
    bool operator() (const Nick &n) 
     { return n.username == toFind; } 
    string toFind; 
}; 

int main() 
{ 
    vector<Nick> vn(10); 
    string nameToFind = "something"; 
    find_if(vn.begin(), vn.end(), UsernameIs(nameToFind)); 
} 

Tenga en cuenta que en C++ 0x, puede hacer lo mismo con una expresión lambda mucho más concisa.

+0

Me aparece 'error: no coincide con la función UsernameIs'. ¿Cuál podría ser el problema? – Sitesh

Cuestiones relacionadas