Cómo usar std::find/std:: find if con un vector de objetos de clase personalizados?


Tengo una clase que representa a un usuario llamado Nick y quiero usar std::find_if en ella, donde quiero encontrar si el vector de lista de usuarios tiene un objeto incluido con el mismo nombre de usuario que paso. Hice algunos intentos al intentar crear un nuevo objeto Nick para el nombre de usuario que quiero probar y sobrecargar el == operator y luego intentar usar find/find_if en el objeto:

    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 que comparar 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í está mi Nick clase de 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);
    };
};
Author: Speed, 2011-08-04

6 answers

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

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

Intenta 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 debe tener este aspecto:

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

No hay necesidad de "nuevo".

 14
Author: Nikko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-04 10:05:34

Si está utilizando C++0X, puede usar una expresión lambda simple

std::string username = "Nicholas";    
std::find_if(userlist.begin(), userlist.end(), [username](Nick const& n){
    return n.username == username;
})
 36
Author: mkaes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-04 09:49:41

Sé que querías 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.

 9
Author: Schnommus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-11 08:05:27

Está pasando un puntero a la función find. Eliminar lo nuevo:

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

Además, sus operadores deben aceptar sus argumentos por referencia const, no los modifican.

bool operator== (const Nick &n1, const Nick &n2)
 3
Author: Benjamin Lindley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-04 09:42:57

Estoy notando que estás tratando de 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() simplemente crea un temporal y no afecta a this. El reenvío de constructores 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 sobre binary_search cubre los mismos motivos. La respuesta principal es simplemente impresionante.

Restricción mística en std:: binary_search

HTH.

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

 1
Author: Armen Tsirunyan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:04

Puedes usar boost:: bind

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

Simplemente implementa bool Nick:: isFound ()

También puede pasar los criterios

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

Implementar

bool Nick::compare( const Nick & nick )
{
    return this->username == nick.username;
}
 0
Author: Nelstaar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-04 09:51:06