提升精神和抽象语法树设计

时间:2013-02-14 16:03:37

标签: c++ boost boost-spirit abstract-syntax-tree boost-variant

我正在使用Boost Spirit中的Qi来解析VRML 1.0。有一个名为Separator的组节点,紧接在Separator下,可以保存许多不同类型的节点。 AST基于Boost.Variant,到目前为止看起来很冗长。我已接近达到变体中20种类型的限制。我知道我可以扩展变体的类型数量,但我确信必须有更好的方法来设计它。欢迎提示。

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 个答案:

答案 0 :(得分:3)

你确定你没有过早优化吗?根据我的经验,变体的“认知开销”不会随着变体 [1]

中元素类型的数量而增加。

你可能想要

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;

替代地

在这种情况下,您可以使用动态多态性路径来代替静态多态性。

根据您的使用情况,性能不一定会受到严重影响。主要区别是

  1. 要获得完全可优化的访问者代码,您需要使用动态强制转换,其中变体现在为您执行类型化工程
  2. 内存分配的位置可能不太理想(尽管自定义分配器可能会为您缓解一些事情)
  3. 实际上可以改进存储要求(变体必须容纳最大的元素类型;当大多数元素类型实际上更小时,将有效地分配更少的内存)。

    1. 在实践方面,您可能必须使用Phoenix(语义操作)来正确分配属性
  4. 我不推荐它,但很明显你甚至可以使用boost::any

    struct poorMansVariant
    {
          TypeCode discriminator; // TypeCode::Nil, TypeCode::Coordinate3...
          boost::any value;
    };
    

    [1] 虽然当某些元素类型是可转换/可赋值时,情况可能会稍微复杂,或者通常,它们的构造函数变得模糊不清。但这是另一个话题