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 に答える