使用Boost Spirit解析字符后跟可变数量整数的编译问题
问题:Boost Spirit解析可变数量整数编译错误
需求
解析以下格式的字符串:
f 1 2 3 4
f 1 2 3
f 1 2 3 4 5
出错的代码
using boost::spirit::qi::uint_; using boost::spirit::qi::double_; using boost::spirit::qi::_1; using boost::spirit::qi::phrase_parse; using boost::spirit::ascii::space; using boost::phoenix::ref; using boost::phoenix::push_back; std::vector<unsigned int> v; r = phrase_parse(first_, last_, // Begin grammar ( 'f' >> uint_[push_back(ref(v), _1)] >>*(uint_[push_back(ref(v), _1)]) ) , // End grammar space);// Begin grammar
编译错误
- Error C2064: term does not evaluate to a function taking 2 arguments
- Error C2668: 'boost::phoenix::ref': ambiguous call to overloaded function
- Error C2780: 'bool boost::spirit::qi::phrase_parse(Iterator &,Iterator,Expr &,const Skipper &,boost::spirit::qi::skip_flag)': expects 5 arguments - 3 provided
环境说明
使用Boost 1.55版本和MSVC 2015(无法更换)
可正常运行的代码(固定数量整数)
unsigned int v1 = 0, v2 = 0, v3 = 0; r = phrase_parse(first_, last_, // Begin grammar ( 'f' >> uint_[ref(v1) = _1] >> uint_[ref(v2) = _1] >> uint_[ref(v3) = _1] ), // End grammar space);
问题分析与修复
1. 核心问题拆解
旧代码的错误集中在三个点:phrase_parse参数传递、Phoenix动作绑定歧义、语法规则冗余。
2. 修复后的代码
#include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> #include <vector> #include <string> int main() { namespace qi = boost::spirit::qi; namespace phoenix = boost::phoenix; using qi::uint_; using qi::phrase_parse; using qi::_1; using qi::ascii::space; using phoenix::ref; using phoenix::push_back; std::string input = "f 1 2 3 4"; auto first = input.begin(); auto last = input.end(); std::vector<unsigned int> v; bool r; // 用+uint_替代冗余的uint_>>*uint_,匹配1个或多个整数 r = phrase_parse(first, last, 'f' >> +uint_[push_back(ref(v), _1)], space); return 0; }
3. 关键修复点
- 简化语法规则:使用
+uint_替代uint_ >> *uint_,+表示匹配1个或多个目标规则,既符合需求(f后至少有一个整数),又避免重复编写相同的Phoenix动作,减少绑定错误。 - 解决
ref歧义:通过命名空间限定phoenix::ref,避免MSVC 2015中与std::ref的命名冲突,消除C2668错误。 - 修正
phrase_parse参数:确保迭代器参数正确传递,且r明确声明为bool类型,解决C2780的参数数量不匹配问题。 - 清理冗余语法:移除不必要的括号和错位注释,避免编译器解析歧义。
4. 错误原因详解
- C2780错误:旧代码中可能存在迭代器未按引用传递、或语法错误导致编译器匹配到错误的
phrase_parse重载,修复后使用标准的4参数重载即可解决。 - C2064与C2668错误:旧代码中重复的
push_back动作在Boost 1.55与MSVC 2015的组合下,触发了Phoenix函数对象的绑定歧义,简化规则后只保留一次动作,即可消除这类错误。
内容的提问来源于stack exchange,提问作者Ramon Lozano
相关产品推荐
相关产品推荐

