动态过滤对象列表c ++

时间:2016-05-06 14:48:13

标签: c++ filtering

如果我有一个类如:

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

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

我可以使用switch语句,但如果有很多字段,这将无法管理。

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

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

2 个答案:

答案 0 :(得分:2)

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

这具有允许在运行时创建属性的附加优势,因此整个数据模型可以是动态的和数据驱动的。

答案 1 :(得分:1)

语言中没有内置的等效模式:与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;
    }
}

Demo.

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