我尝试编译使用许多模板魔术(主要是元组)的旧代码(json to struct parser),以便我可以描述如下解析器命令:
auto mesh_parser = TupleParser<Mesh&>::create("Mesh list parser");
mesh_parser >> Ops::read("name") >> Ops::cast(&stringNotEmpty) >> Ops::write(&Mesh::name);
mesh_parser >> Ops::read("file") >> Ops::cast(&stringNotEmpty) >> Ops::write(&Mesh::file);
mesh_parser >> Ops::optional() >> Ops::read("submeshes") >> Ops::unlist() >> Ops::cast(&stringNotEmpty) >> Ops::write(&Mesh::submeshes);
此代码构建解析器链以将 json(Qt 库中的 QJsonValue 对象)解压缩为普通结构。
- 读取“name”属性,转换为写入“name”属性(QString)的QString(仅非空,或在其他地方失败);
- 读取“name”属性,转换为写入“name”属性(QString)的QString(仅非空,或在其他地方失败);
- 如果可能,请阅读“submeshes”、unlist(对数组中的每个项目执行)、将(每个项目)转换为非空 QString 并将(每个项目)附加到“submeshres”属性(QList)。
比解析:
Mesh output;
mesh_list_parser->parse(output, json_value);
// where json_value is QJsonValue with something like that:
// {"name":"foo","file":"bar.json","submeshes":["foo","bar","baz"]}
有时这段代码可以完美运行,但 g++ 4.9 尝试在我的代码中未使用的变体中构建模板。
错误:
In file included from ../../Project/src/Render/meshmanager.cpp:4:0:
../../Project/src/Parse/tupleparser.h: In instantiation of 'struct _helpers::packer<Mesh&, QJsonValue>':
../../Project/src/Render/meshmanager.cpp:69:88: required from here
../../Project/src/Parse/tupleparser.h:1144:38: error: creating pointer to member reference type 'Mesh&'
using Field = FieldType Unref::*;
仅在调试和发布构建配置中首次使用Ops::cast
, Ops::write
(以及另外两个命令 -one_of
和)时才会引发此错误。or_else
Ops
- 带有解析器操作的命名空间。从模板Ops::cast
返回对象。_helpers::caster
该对象存储指向转换函数的指针。
我有操作员与演员表助手一起工作:
template<...> ParserNode<%output_tuple_type%> operator >>(ParserNode<%input_tuple_type&>, _helpers::caster<From, To> cmd)
此运算符附加新命令(cast
在本例中)以解析链并返回新节点,但是...我不在有错误的行上使用Ops::packer
(从_helpers::packer
模板返回对象),因此无需operator >>
为Ops::packer
具有此类元组的节点构建类型。每个运算符都是独立编写的,而不是在ParserNode
模板类主体中,所以我希望它g++
只会构建需要的组合。
Qt 项目文件中的这一行:
QMAKE_CXX=g++-4.8
修复了问题(g++ 4.8 可以构建我的代码),但这就像拄着拐杖走路。
我可以设置一些额外的 g++ 参数 (to QMAKE_CXXFLAGS
) 以防止构建未使用的模板组合吗?不想重写这段代码,至少现在......