为什么以下代码保证是唯一的typeID?!
using TypeId = uintptr_t;
template < typename T >
static TypeId GetTypeId()
{
static uint32_t placeHolder;
return (reinterpret_cast<TypeId>(&placeHolder));
}
我不明白为什么这不仅仅是一种随机的记忆位置,而是一种“误用”...感谢您提前回答。
答案 0 :(得分:7)
你是正确的,实现滥用块范围静态变量的&#34;随机存储器位置&#34; ,但这不是意味着您所谈论的保证并不成立:从GetTypeId<T>
返回的内容对于每个实例都是唯一的。
注意:但是应该知道
uintptr_t
不保证可用于每个平台。实现该函数的完全可移植的方法是返回void*
,保证能够保存程序中每个对象的每个地址。
在 C ++ 中,保证每个对象必须驻留在唯一的地址,除非我们讨论的是一个对象,如果是另一个对象则是子对象。在这种情况下,它们可能具有相同的地址(并且在需要共享地址的情况下,与标准布局类及其第一个数据成员一样)。
1.8p6
C ++对象模型[intro.object]
除非对象是零字段或零大小的基类子对象,否则该对象的地址是它占用的第一个字节的地址。如果一个是另一个的子对象,或者如果至少一个是零大小的基类子对象并且它们是不同类型的,则不是位字段的两个对象可以具有相同的地址;否则,他们将拥有不同的地址。
我们还有一个明确的子句,说明包含 static 变量的函数模板的每个特化都有自己的静态变量的唯一副本:
14.8p2
功能模板专精[temp.fct.spec]
从模板实例化的每个函数模板特化都有自己的任何静态变量的副本。
由于声明为 static 的变量对GetTypeId<T>
的每个实例都是唯一的,其中T
是任意类型,因此每个对象名为placeHolder
模板专业化必须是一个独特的对象。
它必须是一个独特的对象,并且随之而来;它必须有一个独特的地址。
注1)在 C ++ 11 中,我们
std::type_index
符合您的保证。
注2) C ++ 11 标准草案n3337已在本文中用作参考。