我需要将编译时类型信息(名称、字段...)存储在一个可以在运行时迭代的列表中。我想出了一些看起来像这样的东西:
#include <stdio.h>
struct Type
{
const char *m_szName;
Type *m_pNext;
};
struct TypeList
{
static Type *ms_pHead;
static Type *Push(Type *pHead)
{
Type *pNext(ms_pHead);
ms_pHead = pHead;
return pNext;
}
};
Type *TypeList::ms_pHead = 0;
template <typename T>
struct TypeHolder
{
static Type ms_kType;
};
#define _DECLARE_TYPE(_Name) \
template <> Type TypeHolder<_Name>::ms_kType = {#_Name, TypeList::Push(&ms_kType)};
struct A
{
float m_fField;
};
_DECLARE_TYPE(unsigned int);
_DECLARE_TYPE(float);
_DECLARE_TYPE(A);
int main()
{
Type *pType(TypeList::ms_pHead);
while (pType != 0)
{
printf("%s\n", pType->m_szName);
pType = pType->m_pNext;
}
return 0;
}
这样,我需要做的就是声明一个新类型并同时静态注册它是在我的代码中的任何地方使用宏_DECLARE_TYPE。上面的示例将输出:
A
float
unsigned int
在 MSVC9 上,一切正常,我得到输出,直到我打开优化,其中包括“消除未引用的数据 (/OPT:REF)”。如果我这样做,上面的程序没有输出。现在我看到代码中没有直接引用 TypeHolder、TypeHolder、TypeHolder,所以我想链接器正在删除它们,而不管它们的初始化可能有什么副作用。我使用静态初始化的原因是它允许我在代码中的任何位置声明和注册一个类型,而无需创建一个我手动调用的大函数
TypeList::Push(TypeHolder<unsigned int>::ms_kType);
TypeList::Push(TypeHolder<float>::ms_kType);
TypeList::Push(TypeHolder<A>::ms_kType);
对于每种类型。
另外,我希望我的解决方案能够在各种编译器上工作,因此使用仅适用于 MSVC 甚至关闭优化的非标准 #pragma 指令不是一种选择。
我有什么办法可以避免不得不在一个单独的地方(除了宏内部)手动列出所有类型的麻烦吗?