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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6939129/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 20:58:58  来源:igfitidea点击:

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

stlstl-algorithmc++

提问by Speed

I have a class representing a user called Nickand I want to use std::find_ifon 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 Nickobject for the username I want to test and overloading the == operatorand then trying to use find/find_ifon 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 == operatorso 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);
    };
};

采纳答案by Nikko

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".

不需要“新”。

回答by mkaes

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

回答by Seb Holzapfel

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 表达式执行相同的操作。

回答by Benjamin Lindley

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

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

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)

回答by Nelstaar

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

回答by Armen Tsirunyan

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)

好吧,对不起,但这不起作用。该行Nick()只是创建一个临时的,不会影响this. 构造函数转发仅在 C++0x(即将推出的标准)中可用

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.

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

Mystical restriction on std::binary_search

对 std::binary_search 的神秘限制

HTH.

哈。

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

PS 理想情况下,这应该是评论,但它太冗长了