问题
I'm using Qi from Boost Spirit to parse VRML 1.0. There is a group node called Separator and immediately under Separator, many different types of nodes can be held. The AST is based upon Boost.Variant and so far is looking lengthy. I'm close to hitting the limit of 20 types in the variant. I know I can extend number of types a variant has, but I'm sure there must be a better way to design this. Ideas welcome.
typedef boost::variant<
Nil,
Coordinate3,
Info,
Material,
MaterialBinding,
Normal,
NormalBinding,
Texture2,
Texture2Transform,
TextureCoordinate2,
ShapeHints,
MatrixTransform,
Rotation,
Scale,
Transform,
Translation,
boost::recursive_wrapper<Separator>
> VRML1Node;
回答1:
Are you sure you're not optimizing prematurely? In my experience the 'cognitive overhead' of a variant doesn't increase with the number of element types in the variant[1]
You might want to
Use a type sequence to specify bounded types
typedef mpl::vector< Coordinate3 > types_initial;
typedef mpl::push_front< types_initial, Nil >::type types;
boost::make_variant_over< types >::type VRML1Node;
Alternatively
In stead of going for static polymorphism, you could in this case go the dynamic polymorphism route.
Depending on your use, the performance won't necessarily be badly impacted. The main difference would be
- to get completely optimizable visitor code, you need to employ dynamic cast where the variant is doing the type eraruse for you now
- the locality of memory allocations may be less optimal (allthough a custom allocator might alleviate things for you)
the storage requirements might actually be improved (a variant will have to accomodate the largest element type; when most element types are in fact smaller, less memory will effectively be allocated).
- on the practical side, you may have to use Phoenix (semantic actions) to assign the attributes properly
I don't recommend it, but it is clear that you could even use boost::any
struct poorMansVariant
{
TypeCode discriminator; // TypeCode::Nil, TypeCode::Coordinate3...
boost::any value;
};
[1] though the situation may get slightly complex when some element types are convertible/assignable, or in general, their constructors become ambiguous. But that's another topic
来源:https://stackoverflow.com/questions/14878938/boost-spirit-and-abstract-syntax-tree-design