首先,我正在使用MS Visual Studio 2017(v15.19.11),C ++ 14和Boost v1.65.1的默认C ++语言标准
我的输入文件格式如下:
IterName SomeName
IterDesc Some Description
COLUMNS fname.XCT posn.detect.R posn.source.z
expt_KF000000.raw 0.0 27.639320225002102
expt_KF000180.raw 216.34457142857138 30.584848796430673
expt_KF000360.raw 72.68914285714277 33.530377367859245
我正在尝试将其解析并加载到如下结构中:
struct Stax { std::string stage, axis; };
struct Configuration {
std::map<std::string, std::string> filenames; // "expt_KF000000.raw": "XCT", "other_file.raw": "OCT"
std::map<double, Stax> positions; // 0.0: ["Detect", "R"], 27.639: ["Source", "Z"]
};
struct Iteration {
std::string name;
std::string descript;
std::vector<Configuration> configs;
};
包含“ COLUMNS ”的行之后的每一行都应生成一个新的Configuration
实例,并将其添加到Iteration.configs
中。
如代码中的注释所暗示,某些列可能会丢失(在此示例中为“ fname.OCT ”)...但是列的顺序可能会有所不同(数量也会有所不同) ),因此我尝试使用本地规则状态来保存可变数量的解析器,每列对应一个解析器,如下所示:https://stackoverflow.com/a/31382602/1206102
Configuration.positions
的元素由“ posn。”标题字符串后面的信息以及从单元格本身解析的所有内容组成。同样,Configuration.filenames
的元素由标题中“ fname。”后面的任何内容以及单元格内容组成。因此,我必须以某种方式保存我从标头行中解析的信息,以便稍后在解析单元格时使用...因此我将其与单元格解析器一起存储在规则本地状态var中。
我已经尝试了各种方法,从规则局部变量到Phoenix封装的数据成员,从直接属性传播到融合适应的结构和“定制点”,甚至是attr_cast
与transform_attribute
专业化...但尚未成功编译。我的尝试清单如下:
我的上一次尝试仍然会产生11个编译时错误,其中第一个错误('const_iterator': is not a member of 'Configuration'
告诉我们:某事(Qi / Fusion / Phoenix)期望Configuration
是可迭代的……可能因为填充它的解析类型是(元组的向量)。
这可能是我问题的症结所在:我正在尝试将已解析的可迭代对象填充到不可迭代*的复杂结构中:已解析向量中的某些元组将进入该结构的一个数据成员,而其他元组将进入将进入另一个数据成员。 (*我说不可迭代,是因为在Configuration
上进行迭代是没有意义的,但是如果Qi / Fusion / Phoenix坚持我可以尝试适应。实际上,您会发现[注释]试图定义{ {1}的{1}}类型。)
如果可能的话,我想使用Boost.Spirit完成此操作...任何想法我做错了什么?
答案 0 :(得分:1)
&cell_stage
的地址不为cell_stage
,因为operator&
已超载。使用boost/std::addressof
获取地址。qi::rule<Iterator, Skipper, double()>*
无法转换为qi::rule<Iterator, Skipper, boost::variant<std::string, double, bool>>*
qi::eps[_offset = -1, px::ref(_ncols) = px::size(_tstore)]
中,您只需在初始化时将-1
分配给_offset
,它就必须是px::ref(_offset) = -1
qi::repeat(_ncols)
不会重复_ncols
次,而是重复_ncols
在规则创建时包含的数字,该数字为零。qi::eps[_offset = ++_offset % _ncols]
中,与之前的一样,您不会创建Phoenix lambda,而只会创建qi::eps[0]
之类的东西。它必须是qi::eps[px::ref(_offset) = ++px::ref(_offset) % px::cref(_ncols)]
。qi::attr(_tstore[_offset]) >> *_pstore[_offset]
应该做什么,但显然不是您的意思,可能是qi::lazy(px::cref(_tstore)[_offset]) >> qi::lazy(px::cref(_pstore)[_offset])
。在这一点上,我不得不停下来问:您真的要使它正常工作吗?
请勿将Spirit用作Birmingham screwdriver。您不必被迫在单个Spirit解析器中完成所有操作。例如,您可以在一个普通的for循环中解析行,这将使编写和维护更加简单。