2013-12-19 13 views
6

Ich frage mich, ob Qt eine Alternative zu Typid bietet, um variable Typen zu erkennen und ihren Namen in einem für Menschen lesbaren Format zu erhalten. Mein spezifisches Problem ist folgendes: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); 
} 

die Idee, dass verallgemeinern eine Variable sein würde als eine Eingabe an Funktionen zu nutzen. Als Nebenknoten tyeinfo richtig auf meinem System scheint (ich bin mit MinGW auf Windows 7) nicht zu arbeiten, wenn ich versuche:

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

i 
7QString 
d 
f 

Jeder Vorschlag bekommen?

+2

Ich denke, die Ausgabe für Ihr Programm ist die erwartete Ausgabe. Wenn ich die Namen der Variablen "i", "d" und "f" ändere, gibt es mir immer noch diese Zeichenfolgen. Die genaue Schreibweise der Ausgabe von 'typeid :: name()' ist Implementierung definiert, und es scheint, dass Sie einen Namen geben, der sich auf den verstümmelten C++ - Namen für den Typ bezieht. Das macht tatsächlich eine gewisse Menge Sinn. –

+1

Typeinfo funktioniert wie geplant auf Ihrem System. Warum glaubst du, gibt es ein Problem? –

+0

Sie brauchen Qt dafür nicht. Die meisten C++ - Implementierungen bieten das, was Sie benötigen, obwohl es in gewissem Umfang Compiler-spezifisch ist. –

Antwort

4

könnten Sie this verwenden:

const char * QVariant::typeName() const

Gibt den Namen der in der Variante gespeicherten Typ. Die zurückgegebenen Zeichenfolgen beschreiben den C++ - Datentyp, der zum Speichern der Daten verwendet wird: z. B. "QFont", "QString" oder "QVariantList". Eine ungültige Variante gibt 0 zurück.

Dies funktioniert für POD und registrierte integrierte Qt-Typen. Sie müssen jedoch die following method für die Registrierung Ihres benutzerdefinierten Typs verwenden.

int qRegisterMetaType(const char * typeName)

Eine andere Sache, die Sie versuchen könnten, obwohl es etwas überflüssig QVariant ist mit Objekt QMetaObject in der folgenden Art und Weise zu arbeiten:

const char * QMetaObject::className() const

Gibt den Klassennamen.

und

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

Gibt einen Zeiger auf das Meta-Objekt dieses Objekts.

Ein Metaobjekt enthält Informationen über eine Klasse, die QObject erbt, z. Klassenname, Superklassenname, Eigenschaften, Signale und Slots. Jede QObject-Unterklasse, die den Q_OBJECT-Makro enthält, wird ein Meta-Objekt haben.

Die Meta-Objektinformationen werden vom Signal/Slot-Verbindungsmechanismus und vom Eigenschaftensystem benötigt. Die Funktion eres() verwendet auch das Meta-Objekt.

Wenn Sie keinen Zeiger auf eine tatsächliche Objektinstanz haben, aber trotzdem auf das Metaobjekt einer Klasse zugreifen möchten, können Sie staticMetaObject verwenden.

Es ist unnötig zu sagen, dass dies nur für QObjects funktioniert, also nicht für QString usw. Sie müssten QObject-Unterklassen erstellen.

Es gibt auch einige QMetaType, die Sie für die Erstellung verwenden können, aber this ist ein bisschen anders, so erwähne ich hier nur auf Vollständigkeit:

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

Liefert ein Handle auf den Typ namens typeName oder QMetaType :: UnknownType, wenn es keinen solchen Typ gibt.

Hier können Sie alle Arten finden:

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

0

Es sieht so aus, dass Sie mit universellen Variablen zu bekommen versuchen, so etwas wie QVariant. QVariant funktioniert perfekt für alle Grundtypen und alle Qt-Typen. Andere Arten können registered zum Qt-Meta-Datensystem sein.

1

Sie erhalten verstümmelte Namen. Das ist völlig in Ordnung, da das Verhalten der Implementierung definiert ist. Um es lesbar zu machen, müssen Sie die Namen auf den Compilern, die die Namen (gcc und llvm) zerlegen, abmildern.

Das Folgende funktioniert unter g ++, llvm-C++ und MS Visual C++, also ist es ungefähr so ​​portabel, wie man vernünftigerweise erwarten kann.

#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); 
} 

Ausgabe von gcc und LLVM:

int 
QEvent 
MyEvent 

Ausgabe von MSVC:

int 
class QEvent 
class MyEvent