我在互联网上找到了一个简单的解决方案,用于没有内置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 ++尝试了这个带有不同优化值的代码,一切似乎都没问题。
答案 0 :(得分:12)
首先:有一个专门用于包含指针的整数类型:
intptr_t
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的对象识别。您可能想了解他们实施isa
,cast
和dyn_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) = 4
,sizeof(void (*)()) = 8
上,因此可能发生冲突并且无法预测。
您可以转换为适当大小的积分,但理论上它仍然是未定义的行为。