std::按成员查找对象

2022-01-20 00:00:00 find c++ member stl

我在使用 STL 时遇到了减速带,这似乎是一种正常的场景,在这里简化一下:

I’ve run into a speedbump while using the STL with what seems like a normal scenario, simplified here:

class Person {
  string Name;
  int    Age;
};

vector<Person> people;
AddPeople(people);

string s("Bob");
find(people.begin(), people.end(), s);

问题

不幸的是find想比较整个类.

有没有更好或更合适的方式来做到这一点STL 方式"?建议的问题没有帮助,但我设法找到了几个 相关 问题a> 但没有直接的解决方案.

Is there a better or more appropriate way to do this the "STL way"? The suggested questions weren’t helpful, but I managed to find a couple of related questions but no direct solution.

有一些潜在的解决方法:

There’s some potential work-arounds:

  1. 完全放弃find(杂乱无章,但可以重构):

  1. Forgo find altogether (cluttered, but could be refactored):

bool bBob = false;for (UINT i = 0; i < people.size(); i++) {if (people[i].Name == s)bBob =真;休息;}

bool bBob = false; for (UINT i = 0; i < people.size(); i++) { if (people[i].Name == s) bBob = true; break; }

提供转换运算符(隐式转换不起作用;find中不能使用显式):

Provide conversion operator (implicit conversion doesn’t work; explicit can’t be used in find):

类人{字符串名称;诠释年龄;运算符字符串(){返回名称;}};

class Person { string Name; int Age; operator string() {return Name;} };

人 b (Bob", 99);字符串 s(Bob");b == s;//不起作用字符串(b) == s;//有效,但对 find() 没有好处

Person b ("Bob", 99); string s ("Bob"); b == s; //doesn’t work string(b) == s; //works, but no good for find()

定义一个独立的相等运算符(简单、有效但全局公开):

Define a standalone equality operator (simple, effective, but globally exposed):

BOOL 运算符==(人 l,字符串 r){返回 l.Name == r;}

BOOL operator==(Person l, string r) { return l.Name == r; }

定义一个成员相等运算符(使比较顺序依赖;对象必须在前):

Define a member equality operator (makes comparison order dependent; object must be first):

类人{字符串名称;诠释年龄;bool operator==(string s) {return Name == s;}};

class Person { string Name; int Age; bool operator==(string s) {return Name == s;} };

人 b (Bob", 99);字符串 s(Bob");b==s;//作品s==b;//不起作用,但 find() 没有问题

Person b ("Bob", 99); string s ("Bob"); b==s; //works s==b; //doesn’t work, but not a problem for find()

看起来#4 是最好的候选人,但没有一个看起来很理想或感觉STL",而且有些有问题.

It looks like #4 is the best candidate, but none seem ideal or feel "STL", and some have problems.

推荐答案

有没有更好或更合适的方式来做到这一点STL 方式"?

Is there a better or more appropriate way to do this the "STL way"?

您可以使用 std::find_if(由 C++11 lambda 驱动):

You can use std::find_if (powered by C++11 lambdas):

std::string name = "Bob";
// ...
std::find_if(std::begin(people), std::end(people), 
    [&] (Person const& p) { return p.Name == name; }

请注意,称其为STL 方式"是不恰当的.这是 C++ 标准库,而不是 STL(标准模板库").STL 为 C++ 标准库的容器和算法库提供了强大的灵感,但两者并不相同.有关详细信息,请参阅此关于 StackOverflow 的问答.

Notice, that calling it "STL way" is inappropriate. This is the C++ Standard Library, not the STL ("Standard Template Library"). The STL served as a strong inspiration for the Containers and Algorithms Library of the C++ Standard Library, but the two things are not the same. See this Q&A on StackOverflow for further information.

由于您使用的编译器不支持 lambda,您可以定义自己的函子谓词:

Since you are using a compiler that does not support lambdas, you can define your own functor predicate:

struct person_has_name
{
    person_has_name(std::string const& n) : name(n) { }  
    bool operator () (Person const& p) { return p.Name == name; }
private:
    std::string name;
};

并以这种方式与 std::find_if 一起使用:

And use it with std::find_if this way:

std::string name = "Bob";
// ...
std::find_if(people.begin(), people.end(), person_has_name(name));

相关文章