lundi 4 janvier 2016

Why g++4.9 tries to compile excess code?

I tried to compile my old code (json to struct parser) that use many template magic (mostly tuples), to give me possibility to describe parser commands like this:

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);

This code builds parser chains to unpack json (QJsonValue object from Qt library) to plain struct.

  • Read "name" property, cast to QString (only non-empty, or fail elsewhere) that write to "name" property (QString);
  • Read "name" property, cast to QString (only non-empty, or fail elsewhere) that write to "name" property (QString);
  • If possible, read "submeshes", unlist (perform to every item from array), cast (every item) to non-empty QString and append (every item) to "submeshres" property (QList).

Than parse:

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"]}

Sometimes this code works perfect, but g++ 4.9 tries to build template in variations that is not used in my code.

Error:

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::*;

This error is raised only on first usages of Ops::cast, Ops::write (and on two more commands - one_of and or_else) in debug and release build configurations.

Ops - namespace with parser operation. Ops::cast returns object from _helpers::caster template. This object stores pointer to cast function.

I have operator to work with cast helper:

template<...> ParserNode<%output_tuple_type%> operator >>(ParserNode<%input_tuple_type&>, _helpers::caster<From, To> cmd)

This operator append new command (cast in this case) to parse chain and returns new node, but... I don't use Ops::packer (that returns object from _helpers::packer template) on lines with errors, so no need to build operator >> for Ops::packer for node with such tuple types. Each operator is written standalone, not in ParserNode template class body, so I expect that g++ will build only needed combinations.


This line in Qt project file:

QMAKE_CXX=g++-4.8

Fixes the problem (g++ 4.8 can build my code), but this is like walk on crutches.

Can I set some additional g++ parameters (to QMAKE_CXXFLAGS) to prevent building unused templates combinations? Don't want to rewrite this code, at least now...

Aucun commentaire:

Enregistrer un commentaire