没有RTTI的类标识

时间:2012-06-17 11:06:57

标签: c++ identity rtti

我在互联网上找到了一个简单的解决方案,用于没有内置C ++ RTTI的身份类。

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 ++尝试了这个带有不同优化值的代码,一切似乎都没问题。

3 个答案:

答案 0 :(得分:12)

首先:有一个专门用于包含指针的整数类型:

  • intptr_t
  • 和C ++ 11 uintptr_t

其次,即使在gcc实践中它们是相同的,指向对象的指针的大小和函数指针(或指向成员的指针)的大小也可能不同。因此,使用特定对象而不是方法本身(对于标准一致性)会更好。

第三,它只给你身份,而RTTI更丰富,因为它知道给定对象可以强制转换的所有子类,甚至允许跨虚拟继承进行交叉转换或强制转换。

但是,我猜错了更正的版本:

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

在层次结构中,使用virtual函数返回该ID。

为了完整起见,我会提到Clang和LLVM有自己的方法来处理没有RTTI的对象识别。您可能想了解他们实施isacastdyn_cast here的方式。

答案 1 :(得分:0)

此版本避免了未定义的行为(和编译器警告):

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

答案 2 :(得分:-1)

此解决方案将函数指针强制转换为int。虽然在实践中int

,但无法保证此指针适合sizeof(void *) == sizeof(void (*)()) <= sizeof(int)

编辑:我的坏。在x86_64 sizeof(int) = 4sizeof(void (*)()) = 8上,因此可能发生冲突并且无法预测。

您可以转换为适当大小的积分,但理论上它仍然是未定义的行为。