13

インターネット上のどこかで、組み込みの C++ 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++ でさまざまな最適化値で試してみましたが、すべて問題ないようです。

4

3 に答える 3

12

まず、ポインタを含むように特別に作成された整数型があります。

  • intptr_t
  • そしてC++11でuintptr_t

第 2 に、実際には gcc では同じですが、オブジェクトへのポインターのサイズと関数ポインター (またはメンバーへのポインター) のサイズは異なる場合があります。したがって、メソッド自体よりも特定のオブジェクトを使用する方が適切です (標準準拠のため)。

第三に、特定のオブジェクトをキャストできるすべてのサブクラスを認識し、クロスキャストまたは仮想継承全体のキャストを許可するため、RTTI ははるかに豊富ですが、ID を提供するだけです。

それでも、修正されたバージョンは役立つと思います。

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

そして階層では、virtualその ID を返す関数があります。

完全を期すために、Clang と LLVM には、RTTI を使用せずにオブジェクト識別を処理する独自の方法があることを述べておきます。彼らの実装方法についてはisaこちらcastを参照してください。dyn_cast

于 2012-06-17T11:23:26.377 に答える
0

このバージョンでは、未定義の動作 (およびコンパイラの警告) が回避されます。

template <typename T>
class Identity {
public:
    static const int* id() { static const int id = 0; return &id; }
};
于 2012-06-17T11:23:27.393 に答える
0

このソリューションは、関数ポインタを にキャストしますint。このポインターが に収まるという保証はありませんintが、実際にはsizeof(void *) == sizeof(void (*)()) <= sizeof(int)

編集:私の悪い。x86_64sizeof(int) = 4ではsizeof(void (*)()) = 8、 、そのため、衝突が発生する可能性があり、予測できません。

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

于 2012-06-17T11:11:25.860 に答える