std::find Object by Member
在使用STL的情况下,我遇到了一个超速跳车,这看起来很正常,此处简化了:
1 2 3 4 5 6 7 8 9 10 | class Person { string Name; int Age; }; vector<Person> people; AddPeople(people); string s("Bob"); find(people.begin(), people.end(), s); |
问题
不幸的是,
问题
是否有更好或更合适的方式来执行" STL方法"?建议的问题没有帮助,但我设法找到了两个相关问题,但没有直接解决方案。
解决方法/测试
有一些可能的解决方法:
完全放弃
1 2 3 4 5 6 | bool bBob = false; for (UINT i = 0; i < people.size(); i++) { if (people[i].Name == s) bBob = true; break; } |
提供转换运算符(隐式转换不起作用;显式不能在
1 2 3 4 5 6 7 8 9 10 | class Person { string Name; int Age; operator string() {return Name;} }; Person b ("Bob", 99); string s ("Bob"); b == s; //doesn’t work string(b) == s; //works, but no good for find() |
定义一个独立的相等运算符(简单,有效,但全局公开):
1 2 3 | BOOL operator==(Person l, string r) { return l.Name == r; } |
定义一个成员相等运算符(使比较顺序依赖;对象必须是第一个):
1 2 3 4 5 6 7 8 9 10 | class Person { string Name; int Age; bool operator==(string s) {return Name == s;} }; Person b ("Bob", 99); string s ("Bob"); b==s; //works s==b; //doesn’t work, but not a problem for find() |
看起来#4是最佳人选,但似乎没有一个是理想的或没有" STL"的感觉,并且有些还存在问题。
Is there a better or more appropriate way to do this the"STL way"?
您可以使用
1 2 3 4 | 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上的此问答。
编辑:
由于使用的编译器不支持lambda,因此可以定义自己的函子谓词:
1 2 3 4 5 6 7 | 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; }; |
并通过
1 2 3 | std::string name ="Bob"; // ... std::find_if(people.begin(), people.end(), person_has_name(name)); |
我想您希望这些用于共享名为name的属性的子类或类,如果没有,您可以自己创建一个简单的函数。如果您希望它适用于具有属性名称的任何类,则可以创建如下模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 | template < class ClassWithNameProperty > ClassWithNameProperty * searchName (std::string name, std::vector<ClassWithNameProperty *> array) { for (ClassWithNameProperty * obj: array) { if (obj.compare(obj->name)) { return obj; } } return NULL; } |
或者,但是您希望搜索功能正常工作,希望这对您有所帮助
有两种方法可以实现,所有方法都涉及某种可调用对象和
首先是使用新的C ++ 11 lambda:
1 2 | std::find_if(people.begin(), people.end(), [](const Person& person) { return person.Name =="Bob"; }); |
如果您有不支持lambda的较旧的编译器,则可以使用functor对象:
1 2 3 4 5 6 7 8 9 10 11 12 | class FindPersonByName { std::string name; public: FindPersonByName(const std::string& name) : name(name) {} bool operator()(const Person& person) const { return person.Name == name; } }; std::find_if(people.begin(), people.end(), FindPersonByName("Bob")); |
当然,这两个都要求您的班级公开