结构成员的布尔表达式求值器

Boolean expression evaluator on struct members

背景

我有一个结构:

struct event {
    uint16_t id;
    uint8_t type;
    std::string name;
    // many more fields (either string or integer types)
};

一个布尔表达式(存储在一个字符串中):

name = "xyz" and (id = 10 or type = 5)

我有一个事件对象向量(数千)std::vector<event>,想检查它们是否满足布尔表达式。

到目前为止我已经实现的事情

bool match(const event& ev, const ast::node& node) {
    if (node.first == "name") {
        return (ev.name == node.second);
    } else if (node.first == "id") {
        return (ev.id == std::stoi(node.second));
    } else if (node.first == "type") {
        return (ev.type == std::stoi(node.second));
    } // more else if blocks for each member of event struct
    ...
}

问题

该结构包含 10 个成员。我想避免不必要的比较。在最坏的情况下,一个 AST 终端节点(例如,pair<"type", "5000">)可能会导致 10 次比较。

我尝试构建这个查找映射:

std::map<std::string, std::size_t> fields;

fields["name"] = offsetof(event, name);
fields["id"] = offsetof(event, id);
fields["type"] = offsetof(event, type);

使用这张地图,我可以将 match() 简化为:

bool match(const event& ev, const ast::node& node) {
    const auto offset = fields[node.first];
    return ((ev + offset) == node.second); // DOESN'T WORK
}
  1. 我可以使用 (eventObj + offset) 在偏移量处访问结构成员。如何将其转换为正确的数据类型以便进行比较?

  2. 目前AST终端节点的所有字段值为std::string。如何在分词器或解析步骤中将其转换为正确的类型?我可以将 AST 节点存储为 std::pair<std::string, std::any> 但仍然需要 std::any_cast.

    的类型信息

如果我能以某种方式将类型信息存储在字段映射中,这两个问题都可以解决。我不确定如何。

构建从字段名称到 std::function<std::function<bool(event const&)>(std::string const&)> 的映射,如:

lookup["name"]=[](auto str){
  return [val=std::move(str)](auto& e){
    return e.name==val;
  };
};

现在您可以将对转换为测试函数。

现在你的

name = "xyz" and (id = 10 or type = 5)

变成

tree(
  lookup["name"]("xyz"), 
  std::logical_and<>{},
  tree(
    lookup["id"]("17"),
    std::logical_or<>{},
    lookup["type"]("5")
  )
);

有成堆的工作。