exprtk函数合成成功后符号表中缺失函数名问题排查
问题根源
你遇到的问题核心在于:function_compositor实例是add_function函数内的局部变量,当该函数执行完毕后,这个局部的compositor会被销毁。而exprtk的设计中,function_compositor会管理它添加到符号表中的所有合成函数,一旦它被销毁,这些函数会被自动从符号表中移除,所以后续编译表达式时,符号表中已经没有incrementor函数了。
解决方法
你可以通过延长function_compositor的生命周期来解决这个问题,以下是两种常用的可行方式:
方式一:让compositor生命周期与符号表绑定
修改主函数,将compositor定义为主函数内的变量,再把它的引用传入add_function,确保它的生命周期覆盖符号表的整个使用周期:
// 修改add_function,接收compositor的引用 void add_function(exprtk::symbol_table<double>& symtab, exprtk::function_compositor<double>& compositor) { using function_t = typename exprtk::function_compositor<double>::function; const bool res = compositor.add( function_t("incrementor") .var("x") .expression("x + 1;")); if (!res) { printf("comp err!"); } } // 主函数逻辑 int main() { using symbol_table_t = exprtk::symbol_table<double>; using expression_t = exprtk::expression<double>; using parser_t = exprtk::parser<double>; using compositor_t = exprtk::function_compositor<double>; double x = 123.0; symbol_table_t symbol_table; expression_t expression; parser_t parser; compositor_t compositor(symbol_table); // 生命周期与符号表一致 symbol_table.add_variable("x", x); add_function(symbol_table, compositor); // 传入compositor引用 expression.register_symbol_table(symbol_table); const std::string program = "incrementor(x)"; if (!parser.compile(program,expression)) { printf("err: %s\n",parser.error().c_str()); return 1; } double result = expression.value(); printf("Result: %f\n", result); return 0; }
方式二:将compositor声明为静态变量
在add_function内把compositor定义为静态变量,这样它的生命周期会延续到整个程序结束,不会随函数返回而销毁:
void add_function(exprtk::symbol_table<double>& symtab) { using compositor_t = exprtk::function_compositor<double>; using function_t = typename compositor_t::function; static compositor_t compositor(symtab); // 静态变量,生命周期覆盖整个程序运行期 const bool res = compositor.add( function_t("incrementor") .var("x") .expression("x + 1;")); if (!res) { printf("comp err!"); } }
验证说明
修改后重新编译运行,调试时再检查符号表,incrementor函数会保持存在,parser.compile能成功执行,最终表达式计算结果应为124.0。
内容的提问来源于stack exchange,提问作者Samuel D.
相关产品推荐
相关产品推荐

