Мне нужно каталогизировать все классы, используемые в проекте, чтобы эти классы могли быть созданы на лету из фабрики [...]
Если не использовать 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", а не просто "string").
Мы используемэто решение в качестве альтернативы для boost :: any, которое мы предоставляем через наш SDK (и поэтому не можем использовать boost, так как это потребовало бы, чтобы у наших пользователей была установлена boost, или чтобы мы отправляли части boost в случае чего это может привести к конфликтамдля пользователей, у которых установлены разные версии boost).Он не такой автоматический, как boost :: any, так как требует ручной регистрации поддерживаемых типов (в этом отношении ближе к boost :: variable), но не требует от наших пользователей SDK включения RTTI и работает переносимо через границы модуля (I 'я не уверен, можно ли полагаться на RTTI для получения одной и той же информации в разных компиляторах, настройках и модулях - я сомневаюсь в этом).
Теперь вы можете использовать эти идентификаторы строк, связанные с типом, как вам угодно.Одним из примеров может быть использование его для сопоставления функций создания с этими строковыми идентификаторами, чтобы вы могли создать экземпляр std :: string, например, через factory :: create ("std :: string");Обратите внимание, что это гипотетический случай только для демонстрационных целей, поскольку использование фабрики для создания std :: string было бы довольно странным.