-2

一意の決定論的な名前を持つさまざまなデータ型をC++で生成したいと思います。例えば:

struct struct_int_double { int mem0; double mem1; };

現在、私のコンパイラはカウンタを使用して名前を合成します。つまり、同じデータ型を個別の変換単位でコンパイルする場合、名前は一致しません。

動作しないものは次のとおりです。

  1. ABIMangled_name関数を使用します。すでに一意の名前を持つ構造体に依存しているためです。構造体が匿名であるふりをすることにより、C ++ 11準拠のABIで機能する可能性がありますか?

  2. テンプレートは再帰型では機能しないため、struct2などのテンプレート。

  3. 完全なマングリング。あまりにも長い名前を付けるからです(数百文字!)

グローバルレジストリ(YUK!)とは別に、私が考えることができる唯一のことは、最初に一意の長いマングル名を作成し、次にダイジェストまたはハッシュ関数を使用してそれを短縮することです(衝突がないことを願っています)。

実際の問題:タプル、合計型、関数型など、型が匿名の場合に呼び出すことができるライブラリを生成する。

他のアイデアはありますか?

編集:再帰型問題の追加の説明。次のようなリンクリストを定義することを検討してください。

template<class T>
typedef pair<list<T>*, T> list;

これが実際に必要なことです。これは2つの理由で機能しません。1つは、typedefをテンプレート化できないことです。[いいえ、typedefを含むテンプレートクラスは使用できません。機能しません]次に、list *はまだ定義されていないため、引数として渡すことはできません。ポリモーフィズムのないCでは、次のことができます。

struct list_int { struct list_int *next; int value; };

いくつかの回避策があります。この特定の問題については、Barton-Nackmanトリックの変形を使用できますが、一般化されていません。

一般的な回避策があります。最初にGabrielledesRoisによって示され、オープン再帰のテンプレートを使用し、次に部分的に特殊化してそれを閉じます。しかし、これを生成することは非常に困難であり、私がそれを行う方法を理解できたとしても、おそらく読めないでしょう。

バリアントを適切に実行することにも別の問題がありますが、それは直接関係していません(構築可能な型で結合を宣言することに対する愚かな制限のため、さらに悪いことになります)。

したがって、私のコンパイラは単に通常のC型を使用します。とにかくポリモーフィズムを処理する必要があります。それを作成する理由の1つは、テンプレートを含むC++型システムの問題を回避することでした。これにより、名前の問題が発生します。

4

2 に答える 2

1

あなたは実際に同意するために名前が必要ですか?構造体を別々に、異なる名前で、異なる変換単位でreinterpret_cast<>、必要に応じてC++コンパイラを満足させるために定義するだけです。もちろん、それは手書きのコードでは恐ろしいことですが、これはコンパイラによって生成されたコードなので、C ++コードが生成される前に、必要な静的型チェックを実行できます(そして私はそうすると思います)。

私が何かを見逃していて、本当に同意するタイプ名が必要な場合は、あなたはすでにあなた自身の質問に答えていると思います:コンパイラが複数の翻訳ユニットの翻訳間で情報を共有できない限り(いくつかのグローバルレジストリを介して)、私はできます '名前マングリングの明白なものを除いて、型の構造形式から一意の決定論的な名前を生成する方法を参照してください。

名前の長さについては、なぜそれが重要なのかわかりませんか?ハッシュ関数を使用して名前を短縮することを検討している場合は、明らかに人間が読める形式である必要はないのに、なぜ短くする必要があるのでしょうか。

個人的には、ハッシュ関数を気にせずに、既存の名前マングリングスキームと同様のスタイルで、おそらく人間が読める形式の名前を生成します。したがって、生成struct_int_doubleする代わりに、 sid(struct、int、double)またはsi32f64(struct、32ビット整数、64ビットfloat)などを生成できます。このような名前には、直接解析できるという利点があります(これは、デバッグに非常に重要であるように思われます)。

編集

もう少し考え:

  • テンプレート:可能であったとしても、この問題を回避するためのテンプレートコードを生成することに実際の利点はありません。リンカでシンボル名の長さの制限に達することを心配している場合、リンカにはテンプレートの概念がないため、テンプレートは役に立ちません。表示されるシンボルはすべて、C++コンパイラによって生成されたテンプレート構造のマングル形式になります。 felixコンパイラによって直接生成された長いマングル名とまったく同じ問題があります。
  • felixコードで名前が付けられている型はすべて保持し、生成されたC ++コードで直接(またはほぼ直接)使用する必要があります。名前を生成する必要があるのは、felixコードで使用される匿名型の複雑さには、実用的な(ソフトな)可読性/保守性の制約があると思います。あなたの「バリアント」は識別された共用体であると思います。したがって、各コンポーネントパーツには、felixコードで定義された名前(タグ)が必要です。これらの名前も保持できます。(コメントでこれについて言及しましたが、回答を編集しているので、それを含めることもできます)
  • マングル名の長さを減らす:ハッシュ関数を介して長いマングル名を実行するのが最も簡単な方法のように思えます。適切なハッシュ関数を使用し、ハッシュ名に十分なビットを保持している限り、衝突の可能性は許容できるはずです(ハッシュ名をエンコードするためのアルファベットは37文字なので、完全な160ビットのsha1ハッシュは約31文字で記述できます)。ハッシュ関数のアイデアは、ハッシュ名から元の名前に直接戻ることができないことを意味しますが、そうする必要はないかもしれません。そして、私が推測するコンパイルプロセスの一部として、補助的な名前マッピングテーブルをダンプすることができます(または、利用可能な場合は、C構造体定義から名前を再生成することもできます)。または、それでもハッシュ関数が本当に気に入らない場合は、おそらく、適度にコンパクトなビットレベルのエンコーディングを定義するか(37文字の識別子のアルファベットで記述します)、そのビットレベルのエンコーディングで汎用の圧縮アルゴリズムを実行することもできます。分析するのに十分なfelixコードがある場合は、固定圧縮ディクショナリを事前に生成することもできます。もちろん、それは非常に熱狂的なボンカーです。ハッシュを使用するだけです。

編集2:申し訳ありませんが、脳の障害-sha-1ダイジェストは128ではなく160ビットです。


PS。なぜこの質問が反対票を投じられたのかわからない-あなたが取り組んでいるこのコンパイラについてのもう少しの文脈が役立つかもしれないが、それは私には合理的であるように思われる。

于 2010-12-31T17:33:32.690 に答える
0

私はあなたの問題を本当に理解していません。

template<typename T>
struct SListItem
{
    SListItem* m_prev;
    SListItem* m_next;
    T m_value;
};

int main()
{
    SListItem<int> sListItem;
}
于 2010-12-31T16:44:36.047 に答える