プロジェクトで使用されるすべてのクラスをカタログ化する必要があるため、これらのクラスはファクトリ内からオンザフライで作成できます[...]
RTTIを使用する以外に(これを許可されている場合は悪い考えではありません。boost:: anyはこれを行います)、クラス名に文字列を使用するのはどうですか?これはマクロを介して取得できます。
#include <iostream>
#include <string>
using namespace std;
template <class T>
const char* my_type_id()
{
return "Unknown";
}
#define REGISTER_TYPE(some_type) \
template <> inline \
const char* my_type_id<some_type>() \
{ \
return #some_type; \
}
REGISTER_TYPE(int)
REGISTER_TYPE(std::string)
int main()
{
// displays "int"
cout << my_type_id<int>() << endl;
// displays "std::string"
cout << my_type_id<string>() << endl;
// displays "Unknown" - we haven't registered char
cout << my_type_id<char>() << endl;
}
このアプローチの最も優れた点は、このアプローチを使用すると、翻訳ユニットまたはモジュール全体の問題について心配する必要がないことです。注意しなければならないのは名前の競合だけです。その場合、名前空間を指定してそれらを回避することができます(たとえば、単に「文字列」ではなく「std :: string」)。
このソリューションは、SDKを通じて提供するboost :: anyの代わりに使用します(したがって、ユーザーがBoostをインストールする必要があるため、またはBoostの一部を出荷する必要があるため、Boostを使用できません。異なるバージョンのブーストがインストールされているユーザーの競合)。サポートされているタイプの手動登録が必要なため、boost :: anyほど自動ではありませんが(この点ではboost :: Variantに近い)、SDKユーザーがRTTIを有効にする必要はなく、モジュールの境界を越えて移植可能に機能します(I ' mさまざまなコンパイラ、設定、およびモジュール間で同じ情報を生成するためにRTTIに依存できるかどうかはわかりません-私はそれを疑っています)。
これで、これらのタイプに関連付けられた文字列IDを好きなように使用できます。1つの例は、これを使用して作成関数をこれらの文字列IDにマップし、たとえばfactory :: create( "std :: string");を介してstd::stringのインスタンスを作成できるようにすることです。ファクトリを使用してstd::stringを作成するのはかなり奇妙であるため、これはデモ目的の架空のケースであることに注意してください。