C++中如何实现支持逻辑组合的条件判断数据结构?
问题:支持AND/OR逻辑组合的条件存储与评估
我有一个Logic类,用来存储单个待评估的条件,某个对象最多包含20个这类条件。之前用数组存储多个Logic实例,遍历调用evaluate后将所有结果做AND运算,这个方式没问题,但现在需要同时支持AND和OR的逻辑组合,比如实现(Logic1 && Logic2) || Logic3这样的逻辑关系。有没有比数组更合适的数据结构?要求定义结构时具备良好可读性,比如类似以下形式:
LOGIC(HEIGHT, GREATER_THAN, 50), AND, LOGIC(HEIGHT, LESS_THAN, 100), OR, LOGIC(WEIGHT, LESS_THAN, 500)
简化版代码
enum class OPERATION { GREATER_THAN, LESS_THAN }; enum class CONDITION { HEIGHT, WEIGHT }; class Logic { CONDITION con; OPERATION op; double op2; public: bool evaluate(CONDITION con, double op1){ // 修正拼写错误 evaulate→evaluate if(con == CONDITION::HEIGHT) { if(op == OPERATION::GREATER_THAN) { return op1 > op2; } else if(op == OPERATION::LESS_THAN) { return op1 < op2; } } // 补充默认返回值,避免编译警告 return false; } Logic(CONDITION a, OPERATION b, double c) : con(a), op(b), op2(c) {} // 改用初始化列表更规范 }; int main() { std::array<Logic, 2> statements = { Logic(CONDITION::HEIGHT, OPERATION::GREATER_THAN, 7.31), Logic(CONDITION::WEIGHT, OPERATION::LESS_THAN, 100.0) // 希望能添加类似 OR Logic(CONDITION::WEIGHT, OPERATION::LESS_THAN, 100.0) 的逻辑 }; // 遍历并评估的逻辑 }
推荐方案:用std::variant实现可读的混合类型表达式链
数组只能存储同类型元素,无法直接混合存放Logic条件和AND/OR运算符。C++17引入的std::variant可以在同一个容器中存储不同类型的对象,完美匹配你想要的可读性定义方式。
1. 新增逻辑运算符枚举
先定义表示AND/OR的枚举类型:
enum class LOGIC_OP { AND, OR };
2. 定义统一的变体类型
用std::variant封装Logic和LOGIC_OP,让容器能同时容纳两种类型:
#include <variant> #include <array> using LogicExpr = std::variant<Logic, LOGIC_OP>;
现在就可以按照你期望的形式定义逻辑链了:
std::array<LogicExpr, 5> logic_chain = { Logic(CONDITION::HEIGHT, OPERATION::GREATER_THAN, 50), LOGIC_OP::AND, Logic(CONDITION::HEIGHT, OPERATION::LESS_THAN, 100), LOGIC_OP::OR, Logic(CONDITION::WEIGHT, OPERATION::LESS_THAN, 500) };
3. 实现带优先级的评估逻辑
由于AND优先级高于OR,评估时可以分两步处理:先计算所有连续的AND组合,再用OR合并结果:
#include <vector> bool evaluate_logic_chain(const std::vector<LogicExpr>& chain, double height, double weight) { // 第一步:处理所有AND运算,生成中间结果列表 std::vector<bool> intermediate_results; bool current_and_result = true; bool is_first_condition = true; for (const auto& elem : chain) { if (std::holds_alternative<Logic>(elem)) { const Logic& logic = std::get<Logic>(elem); bool cond_result = false; if (logic.con == CONDITION::HEIGHT) cond_result = logic.evaluate(CONDITION::HEIGHT, height); else if (logic.con == CONDITION::WEIGHT) cond_result = logic.evaluate(CONDITION::WEIGHT, weight); if (is_first_condition) { current_and_result = cond_result; is_first_condition = false; } else current_and_result = current_and_result && cond_result; } else if (std::holds_alternative<LOGIC_OP>(elem)) { LOGIC_OP op = std::get<LOGIC_OP>(elem); if (op == LOGIC_OP::OR) { intermediate_results.push_back(current_and_result); is_first_condition = true; } // AND运算符不中断,继续累积结果 } } // 加入最后一组AND的结果 intermediate_results.push_back(current_and_result); // 第二步:处理所有OR运算 bool final_result = false; for (bool res : intermediate_results) final_result = final_result || res; return final_result; }
可选:用宏进一步简化写法
如果想要完全贴合你给出的LOGIC(...)、AND、OR语法,可以定义宏:
#define LOGIC(con, op, val) Logic(CONDITION::con, OPERATION::op, val) #define AND LOGIC_OP::AND #define OR LOGIC_OP::OR
此时逻辑链定义会更简洁:
std::array<LogicExpr, 5> logic_chain = { LOGIC(HEIGHT, GREATER_THAN, 50), AND, LOGIC(HEIGHT, LESS_THAN, 100), OR, LOGIC(WEIGHT, LESS_THAN, 500) };
备选方案:抽象语法树(AST)
如果需要支持括号嵌套的复杂逻辑(比如(Logic1 OR Logic2) AND Logic3),可以采用AST结构:
- 定义基类
ExprNode,包含纯虚evaluate方法; - 派生
ConditionNode(对应单个Logic条件)和BinaryOpNode(对应AND/OR组合,包含左右子节点)。
这种方式扩展性更强,但定义和评估逻辑比表达式链复杂,适合需要深度嵌套逻辑的场景。
内容的提问来源于stack exchange,提问作者user25135401
相关产品推荐
相关产品推荐

