2013-12-19 2 views
6

Мне интересно, является ли Qt альтернативой typeid для распознавания типов переменных и получения их имени в формате, удобном для человека. Моя конкретная проблема заключается в следующем:Qt: typeid alternative

struct gArgument{ 
    QString type; 
    void* arg; 
}; 

void gargConverter(gArgument* oArg, T data){ 
    oArg->type = typeid(data).name(); 
    oArg->arg = static_cast<void*> (&data); 
} 

идея будет то, что обобщающим переменным для использования в качестве входных данных для функций. В качестве побочного узла tyeinfo, похоже, не будет правильно работать на моей системе (я использую MinGW на Windows 7), если я пытаюсь:

int i; std::cout << typeid(i).name() << std::endl; 
    QString s; std::cout << typeid(s).name() << std::endl; 
    double d; std::cout << typeid(d).name() << std::endl; 
    float f; std::cout << typeid(f).name() << std::endl; 

Я получаю

i 
7QString 
d 
f 

Любое предложение?

+2

Я думаю, что выход для вашей программы является ожидаемым выходом. Если я изменяю имена переменных 'i',' d' и 'f', это все равно дает мне эти строки. Точная написание выходного файла 'typeid :: name()' определяется реализацией, и, похоже, это дает вам имя, связанное с измененным именем C++ для типа. На самом деле это имеет определенный смысл. –

+1

Typeinfo работает как ваша система. Почему вы думаете, что есть проблема? –

+0

Для этого вам может не понадобиться Qt. Большинство реализаций на C++ обеспечивают то, что вам нужно, хотя оно специфично для компилятора. –

ответ

4

Вы можете использовать this:

const char * QVariant::typeName() const

Возвращает имя типа, хранящегося в варианте. Возвращенные строки описывают тип данных C++, используемый для хранения данных: например, «QFont», «QString» или «QVariantList». Неверный вариант возвращает 0.

Это будет работать с POD и зарегистрированными встроенными Qt-типами. Вам нужно будет использовать following method для регистрации вашего пользовательского типа.

int qRegisterMetaType(const char * typeName)

Одна другая вещь, которую вы могли бы попробовать, хотя это несколько излишним QVariant является работа с QMetaObject Объекта следующим образом:

const char * QMetaObject::className() const

Возвращает имя класса.

и

const QMetaObject * QObject::metaObject() const [virtual]

Возвращает указатель на мета-объект этого объекта.

Мета-объект содержит информацию о классе, который наследует QObject, например. имя класса, имя суперкласса, свойства, сигналы и слоты. Каждый подкласс QObject, содержащий макрос Q_OBJECT, будет иметь метаобъект.

Информация о метаобъекте требуется механизмом соединения сигнал/слот и системой свойств. Функция inherits() также использует метаобъект.

Если у вас нет указателя на экземпляр фактического объекта, но вы хотите получить доступ к метаобъекту класса, вы можете использовать staticMetaObject.

Излишне говорить, что это будет работать только для QObjects, поэтому не для QString и т. Д. Вам нужно будет создать подклассы QObject.

Существует также некоторые QMetaType, которые вы можете использовать для создания, но this немного отличается, так что я просто упомянуть здесь, чтобы быть полным:

int QMetaType::type(const char * typeName) [static]

Возвращает дескриптор типа typeName или QMetaType :: UnknownType, если такого типа нет.

Здесь вы можете найти все типы:

http://qt-project.org/doc/qt-5.1/qtcore/qmetatype.html#Type-enum

0

Похоже, что вы пытаетесь получить универсальную переменную, что-то вроде QVariant. QVariant отлично подходит для всех основных типов и всех типов Qt. Другие типы могут быть registered для системы метаданных qt.

1

Вы получаете искаженные имена типов. Это прекрасно, так как определяется поведение. Чтобы получить его для чтения человеком, вам нужно разбить имена компиляторов, которые калечат имена (gcc и llvm).

Ниже приведены работы под g ++, llvm-C++ и MS Visual C++, так что это примерно так же портативно, как можно разумно ожидать.

#include <iostream> 
#ifndef _MSC_VER 
#include <cxxabi.h> 
#endif 

struct QEvent { virtual ~QEvent() {} }; 

struct MyEvent : public QEvent {}; 

#ifndef _MSC_VER 
template <typename T> void dumpType(T val) 
{ 
    int status; 
    char * realname = abi::__cxa_demangle(typeid(val).name(), 0, 0, &status); 
    std::cout << realname << std::endl; 
    free(realname); //important! 
} 

template <typename T> void dumpType(T *ptr) 
{ 
    int status; 
    char * realname = abi::__cxa_demangle(typeid(*ptr).name(), 0, 0, &status); 
    std::cout << realname << std::endl; 
    free(realname); //important! 
} 
#else 
template <typename T> void dumpType(T val) 
{ 
    std::cout << typeid(val).name() << std::endl; 
} 
template <typename T> void dumpType(T *ptr) 
{ 
    std::cout << typeid(*ptr).name() << std::endl; 
} 
#endif 

int main() { 
    QEvent * base = new QEvent; 
    QEvent * der = new MyEvent; 
    dumpType(int()); 
    dumpType(base); 
    dumpType(der); 
} 

Выход из GCC и LLVM:

int 
QEvent 
MyEvent 

Выход из MSVC:

int 
class QEvent 
class MyEvent