如何将std::find/std::find_if用于自定义类对象的向量



我有一个类表示一个名为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";
}

我已经重载了== operator,所以比较Nick == Nick2应该工作,但函数返回error C2678: binary '==' : no operator found which takes a left-hand operand of type 'Nick' (or there is no acceptable conversion)

这是我的Nick类供参考:

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

如果你正在使用c++ 0X,你可以使用一个简单的lambda表达式

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

必须在类之外用两个object定义operator==,作为工具函数,而不是成员。

要使它成为友元,只需将函数的声明放在类中。

试试这样:

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

你的find也应该像这样:

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

不需要new

我知道您想重载==操作符,但是同样的事情可以很容易地用谓词完成:

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

请注意,在c++ 0x中,您可以更简洁地使用lambda表达式执行相同的操作。

您正在传递一个指向find函数的指针。删除新的:

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

同时,你的操作符应该通过const引用接受它们的实参,而不是修改它们。

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

我注意到您正试图以这种方式从一个构造函数调用另一个构造函数:

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

嗯,对不起,但这不起作用。Nick()行只是创建了一个临时变量,并不影响this。构造函数转发仅在c++ 0x(即将发布的标准)中可行

至于你的问题-这个问题问了几天前关于binary_search涵盖相同的理由。上面的答案太棒了。

std::binary_search的神秘限制

HTH .

注:理想情况下,这应该是一个注释,但它太啰嗦了

可以使用boost::bind

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

只是实现bool Nick::isFound()

您也可以通过

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

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

这个适合我:

Nick.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.";
}
结果

Nicholas was found.
John was not found.

最新更新