2

我正在使用来自 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;
4

1 回答 1

3

你确定你没有过早优化吗?根据我的经验,变体的“认知开销”不会随着变体中元素类型的数量而增加[1]

你可能想要

使用类型序列指定有界类型

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(语义操作)来正确分配属性

我不推荐它,但很明显你甚至可以使用boost::any

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

[1]虽然当某些元素类型是可转换/可分配的,或者一般来说,它们的构造函数变得模棱两可时,情况可能会变得稍微复杂一些。但这是另一个话题

于 2013-02-15T07:44:43.543 回答