2012-06-17 7 views
13

インターネット上のどこかのC++ RTTIのないアイデンティティクラスに簡単な解決策が見つかりました。RTTIのないクラスID

template <typename T> 
class Identity { 
public: 
    static int64_t id() 
    { 
     static int64_t dummy; 
     return reinterpret_cast<int64_t>(&dummy); 
    } 
}; 

我々はいくつかのクラスIDを必要とするとき、私達はちょうど使用:

Identity<OurClass>::id(); 

私は思ったんだけど、どんな衝突がありますか。異なるクラスの同じID、同じクラスの異なるIDを返すことはできますか?私はこのコードをg ++でさまざまな最適化値で試してみましたが、すべてがOKです。

+0

、はい。関数ポインタが 'int'と同じサイズであるという保証はありません。 –

+1

これは私の興味に関係しています... –

+0

上記の問題を回避するには、静的メンバー関数テンプレートに静的 'int'変数を置き、* that *へのポインタを返す方が良いでしょう。コンパイラは、とにかく関数を最適化します。 – Electro

答えて

12

まずオフ:あっても実際にかかわらず、

  • intptr_t
  • とC++ 11 uintptr_t

秒間に:そのような一体型のポインタを含むように具体的に構成されているタイプがありますgcc上では等しいので、オブジェクトへのポインタのサイズと関数ポインタ(またはメンバへのポインタ)のサイズは異なっている可能性があります。したがって、メソッド自体ではなく特定のオブジェクトを使用する方が良いでしょう(標準適合の場合)。

第3に、RTTIは非常に豊富ですが、特定のオブジェクトをキャストできるすべてのサブクラスを知っていて、仮想継承を介してクロスキャストまたはキャストを許可することもできるため、

それでも、修正されたバージョンは、私が推測するに役立ちます。

struct Foo { 
    static intptr_t Id() { 
     static boost::none_t const Dummy = {}; 
     return reinterpret_cast<intptr_t>(&Dummy); 
    } 
}; 

と階層では、そのIDを返すvirtual機能を有します。

完全性のために、ClangとLLVMは、RTTIなしでオブジェクト識別を処理する独自の方法を持っていると言います。 isa,castおよびdyn_casthereの実装方法についてお読みください。

+0

包括的な説明のためにアップリストされている。 – Electro

+0

ありがとう、しかし、私はなぜ、オブジェクトへのポインタのサイズと関数ポインタのサイズが異なるかもしれない、なぜ私はdidnt得る?あなたは例を挙げることができますか? – pproger

+0

@pproger:仮想メンバ関数ポインタのサイズは、通常のポインタとサイズが異なることがよくあります。これはコンパイラ特有ですが、この優れたcodeprojectの記事でこれについて詳しく読むことができます:http://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possible –

-1

この解決策は、intへの関数ポインタをキャストします。実際にはsizeof(void *) == sizeof(void (*)()) <= sizeof(int)

編集中ですが、このポインタがintに収まるという保証はありません。 x86_64 sizeof(int) = 4の場合、sizeof(void (*)()) = 8なので、衝突が発生する可能性があり、予測できません。

適切なサイズの整数にキャストできますが、理論的には未定義の動作です。

+0

実際には必ずしもそうではありません。 x86-64を試してみてください。 –

+0

ok、コードを編集しました。今何? – pproger

0

このバージョンでは、未定義の動作(およびコンパイラの警告を)回避:原則として

template <typename T> 
class Identity { 
public: 
    static const int* id() { static const int id = 0; return &id; } 
}; 
+0

私はポインタとして戻り値を必要としません。私はintがほしいと思う: – pproger

+0

なぜあなたはそれがポインタかどうか気にしますか? – Electro

+0

私はしません。コードの作者do) – pproger

関連する問題