UpdateX3版本added https://stackoverflow.com/a/33817135/85371
首先,你陷入了一个很深的陷阱:
Qi 规则不适用于auto
. Use qi::copy
或者刚刚使用过qi::rule<>
。你的程序有未定义的行为,实际上它对我来说崩溃了(valgrind 指出了悬空引用的起源)。
所以,首先:
const auto rule = qi::copy(qi::int_ >> ':' >> (qi::int_ % ',') >> qi::eoi);
现在,当您删除程序中的冗余时,您将得到:
重现问题
Live On Coliru http://coliru.stacked-crooked.com/a/5cada4939db63b12
int main() {
test(qi::copy(qi::int_ >> ':' >> (qi::int_ % ',')));
test(qi::copy(qi::int_ >> ':' >> (qi::int_ >> *(',' >> qi::int_))));
}
Printing
1: 2, 3, 4,
1: 2,
原因和解决方法
发生了什么事3, 4
这是解析成功?
嗯,属性传播规则表明qi::int_ >> *(',' >> qi::int_)
暴露了一个tuple<int, vector<int> >
。为了神奇地 DoTheRightThing(TM) Spirit 意外失火并“分配”int
进入属性引用,忽略剩余的vector<int>
.
如果您想让容器属性解析为“原子组”,请使用qi::as<>
:
test(qi::copy(qi::int_ >> ':' >> qi::as<Record::values_t>() [ qi::int_ >> *(',' >> qi::int_)]));
Here as<>
充当属性兼容性启发式的障碍,语法知道你的意思:
Live On Coliru http://coliru.stacked-crooked.com/a/8db6c5bef6e4b548
#include <iostream>
#include <string>
#include <vector>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/qi.hpp>
struct Record {
int id;
using values_t = std::vector<int>;
values_t values;
};
BOOST_FUSION_ADAPT_STRUCT(Record, id, values)
namespace qi = boost::spirit::qi;
template <typename T>
void test(T const& rule) {
const std::string str = "1: 2, 3, 4";
Record record;
if (qi::phrase_parse(str.begin(), str.end(), rule >> qi::eoi, qi::space, record)) {
std::cout << record.id << ": ";
for (const auto& value : record.values) { std::cout << value << ", "; }
std::cout << '\n';
} else {
std::cerr << "syntax error\n";
}
}
int main() {
test(qi::copy(qi::int_ >> ':' >> (qi::int_ % ',')));
test(qi::copy(qi::int_ >> ':' >> (qi::int_ >> *(',' >> qi::int_))));
test(qi::copy(qi::int_ >> ':' >> qi::as<Record::values_t>() [ qi::int_ >> *(',' >> qi::int_)]));
}
Prints
1: 2, 3, 4,
1: 2,
1: 2, 3, 4,