Boost Spirit qi可选分支操作符无法填充结构体全部属性值问题
问题原因
该问题由Boost Spirit Qi的交替解析符|的属性合成规则导致:|要求两个分支的属性签名完全一致,才能将分支内的属性元素自动展开合并到父规则的属性序列中。如果Qi无法推断出两个分支返回完全相同的属性结构,会将整个交替分支的属性包装为单个boost::variant对象,而不是展开为4个独立的double值。
你的代码中,B分支和C分支逻辑上都返回4个double,但由于缺少显式属性声明,Qi没有将两个分支的属性识别为长度为4的double序列,而是将整个(B分支|C分支)的属性作为单个值绑定到了MyStruct的r5字段,剩余的r6/r7/r8未被赋值,保留了未初始化的垃圾值,这就是你看到异常数值的原因。
没有加C分支时,后续是连续的4个double解析规则,属性会直接依次绑定到r5到r8,因此结果符合预期。
解决方法
你可以通过显式指定交替分支的属性类型,引导Qi正确合成属性,有两种常用实现方案:
方案1:使用qi::as强制指定属性结构
直接在交替分支外层加qi::as声明,强制Qi将分支内容解析为长度为4的double序列:
// 先修正real_parser的显式实例化,避免类型推断问题 qi::real_parser<double> d19_12; qi::rule<string::const_iterator, MyStruct()> gr = qi::lit("A") >> d19_12 >> d19_12 >> d19_12 >> d19_12 >> CRLF // 强制指定交替分支返回4个double的fusion序列 >> qi::as<boost::fusion::vector<double, double, double, double>>()[ (qi::lit('B') >> d19_12 >> d19_12 >> d19_12 >> d19_12 >> CRLF) | (qi::lit('C') >> d19_12 >> d19_12 >> d19_12 >> +qi::lit('_') >> qi::attr(0.0) >> CRLF) ];
方案2:单独定义子规则显式声明属性
将第二行的解析逻辑拆分为独立子规则,显式指定其属性类型,避免推断错误:
qi::real_parser<double> d19_12; // 定义第二行解析规则,显式声明返回4个double qi::rule<string::const_iterator, boost::fusion::vector<double, double, double, double>()> second_line_rule = (qi::lit('B') >> d19_12 >> d19_12 >> d19_12 >> d19_12 >> CRLF) | (qi::lit('C') >> d19_12 >> d19_12 >> d19_12 >> +qi::lit('_') >> qi::attr(0.0) >> CRLF); qi::rule<string::const_iterator, MyStruct()> gr = qi::lit("A") >> d19_12 >> d19_12 >> d19_12 >> d19_12 >> CRLF >> second_line_rule;
两种方案都可以让Qi正确将交替分支的4个double值依次绑定到r5到r8,得到你期望的解析结果。
内容的提问来源于stack exchange,提问作者Anton
相关产品推荐
相关产品推荐

