使用Boost Spirit将双整数序列解析到STL vector遇问题求助
嘿,我之前刚好折腾过Boost Spirit的属性绑定,太懂你这种困惑了!咱们一步步拆解问题:
首先你可能误解了文档里的描述——int_ >> int_的属性并不是直接的std::vector<int>,而是boost::fusion::vector<int, int>(一个fusion元组)。文档里说“vector表示任何存储A类型元素的STL容器”,那是针对重复序列解析器的情况(比如*int_、+int_或者repeat(2)[int_]这类会多次匹配同一规则的解析器),而a >> b这种顺序拼接两个独立规则的写法,属性是fusion的tuple类型,对应每个子规则的属性依次排列。
这就是为什么你给int_>>int_绑定接受std::vector<int>的动作会失败——Spirit找不到从fusion tuple到vector的自动转换(或者说你没触发这个转换)。
给你几个解决思路,附代码示例:
1. 改用重复解析器直接生成vector属性
如果你的需求就是解析固定数量的整数到vector里,用repeat(2)[int_]是最直接的,它的属性天然就是std::vector<int>:
#include <boost/spirit/include/qi.hpp> #include <vector> #include <string> #include <iostream> namespace qi = boost::spirit::qi; int main() { std::string input = "123 456"; std::vector<int> nums; // 直接解析到vector,动作也能直接接vector参数 bool ok = qi::parse(input.begin(), input.end(), repeat(2)[int_][[](const std::vector<int>& vec) { for (int num : vec) std::cout << num << " "; }], nums); }
2. 适配fusion tuple到vector,保留int_>>int_写法
如果你一定要用int_>>int_的结构,可以用qi::as<std::vector<int>>()来强制让Spirit把fusion tuple转换为vector:
#include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> #include <vector> #include <string> namespace qi = boost::spirit::qi; namespace phx = boost::phoenix; void process_vec(const std::vector<int>& vec) { // 这里写你的vector处理逻辑 } int main() { std::string input = "123 456"; std::vector<int> nums; bool ok = qi::parse(input.begin(), input.end(), qi::as<std::vector<int>>()[int_ >> int_][phx::bind(&process_vec, qi::_1)], nums); }
3. 直接处理fusion tuple的动作
如果不想转vector,也可以把动作的参数改成fusion tuple的类型,或者直接绑定两个单独的属性:
#include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> #include <vector> #include <string> namespace qi = boost::spirit::qi; namespace phx = boost::phoenix; void process_two_ints(int a, int b) { std::vector<int> vec; vec.push_back(a); vec.push_back(b); // 后续处理vector的逻辑 } int main() { std::string input = "123 456"; // 直接绑定两个子规则的属性 qi::parse(input.begin(), input.end(), int_ >> int_[phx::bind(&process_two_ints, qi::_1, qi::_2)]); }
核心记住这一点:Spirit里不同的解析器组合生成的属性类型是不一样的,顺序拼接(>>)生成fusion元组,重复匹配生成STL容器,搞清楚这个对应关系就不会踩坑啦!
内容的提问来源于stack exchange,提问作者Yuval Kfir

