0

実行時に反復できるリスト内にコンパイル時の型情報 (名前、フィールドなど) を格納する必要があります。私は次のようなものを思いつきました:

#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 ディレクティブを使用したり、最適化をオフにしたりすることはオプションではありません。

すべてのタイプを別の場所 (マクロ内以外) に手動でリストする手間を省く方法はありますか?

4

0 に答える 0