简体   繁体   English

如何将 std::find/std::find_if 与自定义类对象的向量一起使用?

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

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:我有一个表示名为Nick的用户的类,我想在它上面使用std::find_if ,我想在其中查找用户列表向量是否包含包含与我传入的相同用户名的对象。我尝试了一些尝试为我要测试的用户名创建一个新的Nick对象并重载== operator ,然后尝试在该对象上使用find/find_if

    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) .我已经重载了== operator因此比较 Nick == Nick2 应该可以工作,但是该函数返回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);
    };
};

If you are using C++0X you can use a simple lambda expression 如果您使用的是C ++ 0X,则可以使用一个简单的lambda表达式

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

You have to define operator== with two Objects outside your class, as a tool function, not a member. 您必须使用类之外的两个对象来定义operator ==,作为工具函数,而不是成员。

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". 不需要“新”。

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. 请注意,在C ++ 0x中,您可以更加简洁地使用lambda表达式执行相同的操作。

You are passing a pointer to the find function. 您正在传递一个指向find函数的指针。 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. 同样,您的运算符应通过const引用接受其参数,而不修改它们。

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

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 . Nick()只是创建一个临时文件,不会影响this Constructor forwarding is only possible in C++0x (the upcoming standard) 构造函数转发仅在C ++ 0x(即将发布的标准)中可用

As to your problem - this question asked a couple of days ago about binary_search covers the same grounds. 关于您的问题-这个问题在几天前问过有关binary_search的问题是基于同样的理由。 The top answer is just awesome. 最好的答案是太棒了。

Mystical restriction on std::binary_search std :: binary_search的神秘限制

HTH. HTH。

PS Ideally this should have been a comment, but it's just too verbose PS理想情况下,这应该是评论,但是太冗长了

You can use boost::bind 您可以使用boost :: bind

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

just implement bool Nick::isFound() 只需实现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;
}

This works for me:这对我有用:

Nick.h尼克.h

#include <string>

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

    bool operator==(const Nick& refNick) const
    {
        if (username != refNick.username)
            return false;
        if (interest != refNick.interest)
            return false;
        if (email != refNick.email)
            return false;
        if (is_op != refNick.is_op)
            return false;
        return true;
    }

    bool operator!=(const Nick& refNick) const
    {
        if (username == refNick.username)
            return true;
        if (interest == refNick.interest)
            return true;
        if (email == refNick.email)
            return true;
        if (is_op == refNick.is_op)
            return true;
        return false;
    }
};

main.cpp主程序

#include <iostream>
#include <string>
#include <vector>
#include "Nick.h"

int main()
{
    std::vector<Nick> userlist;
    std::string username = "Nicholas";    
    Nick Nicholas(username, false);
    Nick John("John", true);        
    userlist.push_back(Nicholas);

    std::vector<Nick>::iterator it;

    it = std::find(userlist.begin(), userlist.end(), Nick("Nicholas", false));
    if(it != userlist.end())
        std::cout << "\n" << Nicholas.username << " was found.";
    else
        std::cout << "\n" << Nicholas.username << " was not found.";

    it = std::find(userlist.begin(), userlist.end(), John);
    if (it != userlist.end())
        std::cout << "\n" << John.username << " was found.";
    else
        std::cout << "\n" << John.username << " was not found.";
}

Result结果

Nicholas was found.
John was not found.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM