C++ 通过同一基类接口将Symbol动态转换为对应派生类的方案问询
可行实现方案
方案1:基于现有多态架构扩展,无需手动switch转型
首先给Symbol基类新增统一的取值虚接口,两个派生类各自实现该接口返回自身存储的值,你就不需要手动判断type枚举做转型:
struct Symbol { // 原有成员保持不变 virtual std::variant<int, double> getValue() const = 0; virtual ~Symbol() = default; // 补充虚析构避免内存泄漏 }; // IntSymbol 类中添加实现 std::variant<int, double> getValue() const override { return value; } // RealSymbol 类中添加实现 std::variant<int, double> getValue() const override { return value; }
取值的时候直接调用该接口即可自动返回对应类型的值:
auto param_val = param->getValue(); // 自动返回int或double类型的结果
调用JIT生成的函数时,你在生成IR阶段必然知道函数的参数个数和类型,直接匹配取值传入即可:
// 不要用可变参数签名,直接转成JIT生成函数对应的固定参数签名 auto func = reinterpret_cast<double(*)(int, double)>(address); int a = std::get<int>(c->parameters[0]->getValue()); double b = std::get<double>(c->parameters[1]->getValue()); double c_val = func(a, b); // 将结果写入c的存储字段 std::static_pointer_cast<RealSymbol>(c)->value = c_val; c->evaluated = true;
方案2:改用std::variant替代多态类,代码更简洁
完全抛弃多态继承架构,用variant实现类型擦除,代码量更少,也不需要额外维护虚函数表:
enum class Type { int_t, real_t }; struct IntSymbol { int value; bool evaluated = true; }; struct RealSymbol { double value; bool evaluated = true; }; using Symbol = std::variant<IntSymbol, RealSymbol>; struct SymbolTable { std::unordered_map<std::string, Symbol> table; // 对应调整插入、查询接口逻辑即可 };
取值的时候直接用std::visit或者std::get处理即可:
auto func = reinterpret_cast<double(*)(int, double)>(address); int a = std::get<IntSymbol>(table.get("a")).value; double b = std::get<RealSymbol>(table.get("b")).value; double c_val = func(a,b);
如果需要通用处理任意数量参数的JIT函数,可以配合编译期索引序列+std::apply把参数列表打包成tuple后调用,不需要手动写每个参数的取值逻辑。
补充注意点
你原来的函数指针转换写法有问题,不要用(double)(*)(...)的可变参数签名,C/C++的可变参数调用约定和普通固定参数函数不同,你JIT生成的是固定参数的函数,直接转成对应参数列表的固定签名即可,你生成IR的时候已经明确知道参数的类型和个数,完全可以匹配到对应的函数签名。
内容的提问来源于stack exchange,提问作者aneax
相关产品推荐
相关产品推荐

