问题描述
我使用的是来自齐灵升压解析VRML 1.0。有一个叫分离,并立即分离下,许多不同类型的节点可以保持一组节点。 AST是基于Boost.Variant到目前为止期待冗长。我接近20击球类型的变体的限制。我知道我能延长一个类型的变种有一些,但我敢肯定,必须有一个更好的方式来设计这个。想法表示欢迎。
的typedef的boost ::变体LT;
零,
Coordinate3,
信息,
材料,
MaterialBinding,
正常,
NormalBinding,
纹理2,
Texture2Transform,
TextureCoordinate2,
ShapeHints,
MatrixTransform,
回转,
规模,
转变,
翻译,
提高:: recursive_wrapper<隔板>
> VRML1Node;
你确定你不是优化prematurely ?在我的经验一个变体的认知开销'不在该变体与元素类型的数量增加
您可能希望
的typedef MPL ::矢量< Coordinate3> types_initial;
MPL的typedef :: push_front< types_initial,无> ::类型类型;提高:: make_variant_over<类型> ::类型VRML1Node;
或者
在要去静态多态性代替,你可以在这种情况下,去动态多路径。
根据您的使用,性能不一定会受到严重影响。主要的区别是
- 要获得完全优化的访客code,你需要使用动态转换,其中的变量现在正在做的类型eraruse你
- 内存分配的地方可能不太理想(allthough自定义分配器可能会缓解你的东西)
-
存储需求实际上可能改善(变体将不得不适应最大的元素类型;当大多数元素类型实际上更小,更少的内存将有效分配)
。- ,您可能需要使用凤凰(语义动作)来分配的属性正确
在实际的一面
我不建议这样做,但很明显,你甚至可以使用的boost ::任何
结构poorMansVariant
{
类型code鉴别; //类型code ::无,类型code :: Coordinate3 ...
提高::任何价值;
};
虽然情况可能会得到一些时,元素类型转换/分配,或一般稍复杂,它们的构造变得模糊。但是,这是另一个话题。
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;
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
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;
};
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
这篇关于提振精神和抽象语法树设计的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!