5

设想

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

class Person {
  string Name;
  int    Age;
};

vector<Person> people;
AddPeople(people);

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

问题

不幸的是find想比较整个班级。

问题

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

变通方法/测试

有一些潜在的解决方法:

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

    布尔 bBob = 假;for (UINT i = 0; i < people.size(); i++) { if (people[i].Name == s) bBob = true; 休息; }

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

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

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

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

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

  4. 定义一个成员相等运算符(使比较顺序相关;对象必须是第一个):

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

    人 b(“鲍勃”,99);字符串 s ("鲍勃"); b==s; // 工作 s==b; //不起作用,但对于 find() 来说不是问题

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

4

3 回答 3

6

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

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

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 的编译器,因此您可以定义自己的函子谓词:

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

std::string name = "Bob";
// ...
std::find_if(people.begin(), people.end(), person_has_name(name));
于 2013-05-08T16:16:45.363 回答
1

有几种方法可以做到这一点,都涉及某种可调用对象和std::find_if.

首先是使用新的 C++11 lambda:

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

如果您有一个不支持 lambdas 的旧编译器,您可以使用仿函数对象

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

当然,这两者都要求您的班级拥有Name公开的成员。但是您可以将其更改为使用公共GetName函数并将其添加到类中。

于 2013-05-08T16:16:13.157 回答
1

我猜您希望这些用于共享名为 name 的属性的子类或类,如果不是,您可以自己创建一个简单的函数。如果您确实希望它适用于具有属性名称的任何类,您可以创建如下模板:

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

或者无论您希望搜索功能如何工作,希望这对您有所帮助

于 2016-08-29T21:07:25.923 回答