动态筛选对象列表c++

Dynamically filtering a list of objects c++

本文关键字:c++ 列表 对象 筛选 动态      更新时间:2023-10-16

如果我有一个类,比如:

class Car {
  string name;
  int age;
  string manufacturer;
}

我显示了一个汽车列表,其中有一个过滤器下拉列表,包含名称、年龄和制造商。如何比较汽车上的各个属性?

我可以使用switch语句,但是如果有许多字段,这将变得难以管理。

在JS或Objective-C(使用KVC)中,您可以动态访问对象的属性,因此这很容易。

具体来说,我想问C++中访问变量或成员函数的等效模式是什么,因为它是由用户在运行时提供的,所以在编译时无法知道。

通常使用std::map<>来存储属性,而不是单个数据成员。

这还有一个额外的优点,即允许在运行时创建属性,因此整个数据模型可以是动态的和数据驱动的。

该语言中没有等效的模式:与JS、Objective-C和其他具有重量级元数据的语言不同,C++对代码可用的运行时信息量有限,对完成任务没有任何帮助。

然而,这并不意味着没有办法构建自己的元数据。您可以制作一个函数,将字符串值与对象的字段进行比较,将这些函数映射到相应的字段,并使用映射中的函数按名称访问字段(好像):

// Field equality comparers
map<string,function<bool(Car&,string&)>> carFieldEq = {
    {"name", [] (Car &c, string& cmp) { return c.name == cmp; }}
,   {"age", [] (Car &c, string& cmp) { return to_string(c.age) == cmp; }}
,   {"manufacturer", [] (Car &c, string& cmp) { return c.manufacturer == cmp; }}
};
// Field less-than comparers
map<string,function<bool(Car&,string&)>> carFieldLess = {
    {"name", [] (Car &c, string& cmp) { return c.name < cmp; }}
,   {"age", [] (Car &c, string& cmp) { return c.age < std::stoi(cmp); }}
,   {"manufacturer", [] (Car &c, string& cmp) { return c.manufacturer < cmp; }}
};

您可以按如下方式使用这些地图:

auto cars = vector<Car> {
    {"Impala", 10, "Chevrolet"}
,   {"Focus", 3, "Ford"}
,   {"Jetta", 3, "VW"}
};
string fieldNameEq, eqCmp;
cin >> fieldNameEq >> eqCmp;
cout << "==== Cars matching " << fieldNameEq << "==" << eqCmp << ":" << endl;
for (auto &c : cars) {
    if (carFieldEq[fieldNameEq](c, eqCmp)) {
        cout << c.name << " " << c.age << " " << c.manufacturer << endl;
    }
}
string fieldNameLess, lessCmp;
cin >> fieldNameLess >> lessCmp;
cout << "==== Cars matching " << fieldNameLess << "<" << lessCmp << ":" << endl;
for (auto &c : cars) {
    if (carFieldLess[fieldNameLess](c, lessCmp)) {
        cout << c.name << " " << c.age << " " << c.manufacturer << endl;
    }
}

演示。

请注意,carFieldEqcarFieldLess采用任意字符串,该字符串可能不一定与字段的实际名称匹配。