How to use std::find/std::find_if with a vector of custom class objects?

混江龙づ霸主 提交于 2019-11-26 08:16:07

问题


I have a class representing a user called Nick and I want to use std::find_if on it, where I want to find if the userlist vector has an object included with the same username I pass in. I did a few attempts by trying to create a new Nick object for the username I want to test and overloading the == operator and then trying to use find/find_if on the object:

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

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

I have overloaded the == operator so comparing Nick == Nick2 should work, but the function returns error C2678: binary \'==\' : no operator found which takes a left-hand operand of type \'Nick\' (or there is no acceptable conversion).

Here is my Nick class for reference:

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

回答1:


You have to define operator== with two Objects outside your class, as a tool function, not a member.

Then to make it friend just put the declaration of the function inside the class.

try something like this:

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

Also your find should look like this:

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

No need of "new".




回答2:


If you are using C++0X you can use a simple lambda expression

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



回答3:


I know that you wanted to overload the == operator, but the same thing can easily be done with a predicate:

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

Note that in C++0x, you can do the same thing with a lambda expression much more concisely.




回答4:


You are passing a pointer to the find function. Drop the new:

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

Also, your operators should accept their arguments by const reference, they don't modify them.

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



回答5:


I am noticing you are trying to call one constructor from another in this manner:

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

Well, sorry, but this doesn't work. The line Nick() just creates a temporary and doesn't affect this. Constructor forwarding is only possible in C++0x (the upcoming standard)

As to your problem - this question asked a couple of days ago about binary_search covers the same grounds. The top answer is just awesome.

Mystical restriction on std::binary_search

HTH.

P.S. Ideally this should have been a comment, but it's just too verbose




回答6:


You can use boost::bind

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

just implement bool Nick::isFound()

You can also pass the criteria

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

implement

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


来源:https://stackoverflow.com/questions/6939129/how-to-use-stdfind-stdfind-if-with-a-vector-of-custom-class-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!