typeid



  • Mit

    T t;
    typeid(t).name();
    

    kann man ja den Namen einer Klasse at runtime bekomment. Allerdings habe ich gehört, dass das Format des Namen nicht vom Standard fest geschrieben ist. 😞
    Allerdings brauche (das heist hätte gern um tip arbeit zu sparen) ich in meinem Program den Namen einer Klasse, und zwar so, dass es genau, dass ist was man beim definiren der Klasse gebraucht hat. Also:

    class Haus{};
    

    Müsste "Haus" zurückgeben.
    Allerdings

    namespace Tiere{class Hund{};}
    

    müsste Hund zurückgeben.

    Gibt es da irgendein Trick mit dem ich mich drauf verlassen kann, dass das rauskommt? Was sagt der Standard eigentlich genau?

    Der Grund wieso ich das brauche ist, dass ich intern einen Namen haben möchte den man beim Debuggen versteht und der nicht abhängig davon ist als wievielte eine Klasse erschaffen wird wie IDs.



  • geht alles nicht. Bau selbst etwas.



  • Leg dir doch ne map<string, string> an, die als Key typeid(..).name() und
    als value den Klassennamen erhällt. Dann bekommst du per

    mymap[typeid(myclass)]
    

    dein Klassennamen.



  • Drei Möglichkeiten:

    1. manuell:
      1a) virtuelle Funktionen: virtual const char* class_name() { return "Hund"; }
      1b) eine Map über den typeids ...
    map<typeinfo, const char*> class_names;
    class_names[typeid(Hund())] = "Hund"; etc.
    
    1. ein eigener Preprozessor, der die Klasse parst und eine der obigen Dinge implementiert

    2. in die Compilerdoku gucken und den Aufbau der Typnamen in Erfahrung bringen, dann einen Entschlüssler schreiben.

    alle haben verschiedene Vor- und Nachteile, das musst du eben abwägen. Ich würde (3) empfehlen, so schwer kann das ja nicht sein. Vielleicht gibts das auch schon fertig.

    BTW Deine Klasse Hund müsste eigentlich Tiere::Hund heißen, sonst kollidiert sie ja mit anderne Hund-Klassen in anderen Namespaces.



  • Bashar schrieb:

    1b) eine Map über den typeids ...

    map<typeinfo, const char*> class_names;
    class_names[typeid(Hund())] = "Hund"; etc.
    

    So einfach geht das nicht, da der Copy-Ctor von type_info private ist.
    Entweder man bastelt sich eine Klasse um type_info oder man verwendet Pointer.

    Ein Minimalbeispiel:

    #include <typeinfo>
    #include <map>
    #include <iostream>
    using namespace std;
    typedef map<const type_info*, std::string> TypeMap;
    TypeMap names_g;
    
    bool registerClass(const char* n, const type_info* t)
    {
    	if (!names_g.insert(TypeMap::value_type(t, n)).second)
    		throw "class already registered!";
    	return true;
    
    }
    
    template <class T>
    const char* getName() // für MSVC 6.0 muss hier noch ein T* = 0 stehen!
    {
    	if (names_g.find(&typeid(T)) == names_g.end())
    		throw "type not registered!";
    	return names_g[&typeid(T)].c_str();
    }
    
    #define REGISTER_CLASS(className) \
    	const bool reg_##__LINE__ = registerClass(#className, &typeid(className))
    
    class Bar
    {
    };
    REGISTER_CLASS(Bar);
    
    namespace Foo
    {
    	class Bar
    	{
    
    	};
    	REGISTER_CLASS(Foo::Bar);
    }
    int main() 
    {
    	cout << getName<Bar>();	
    	cout << getName<Foo::Bar>();
    }
    


  • @Bashar (Off-Topic): wieso 'typeid(Hund())' und nicht einfach 'typeid(Hund)'?



  • Mangelnde Ahnung von typeinfo meinerseits 😉



  • Entweder man bastelt sich eine Klasse um type_info oder man verwendet Pointer.

    Oder man ist faul und läd sich das ganze fertig runter :p

    http://sourceforge.net/projects/loki-lib/



  • Helium schrieb:

    Entweder man bastelt sich eine Klasse um type_info oder man verwendet Pointer.

    Oder man ist faul und läd sich das ganze fertig runter :p

    http://sourceforge.net/projects/loki-lib/

    Boost'ler können auch die type_info-Klasse aus boost::python verwenden 😉



    1. manuell:
      1a) virtuelle Funktionen: virtual const char* class_name() { return "Hund"; }
      1b) eine Map über den typeids ...

    Naja wenn es mit typeid geht ist das das Rad neuerfunden.

    1. ein eigener Preprozessor, der die Klasse parst und eine der obigen Dinge implementiert

    Es heist, dass es besser ist Preprocessor Instruktionen zu vermeiden, allerdings mit Prepreprocessor Instruktionen hab ich noch keine Erfahrung 🙄 .

    1. in die Compilerdoku gucken und den Aufbau der Typnamen in Erfahrung bringen, dann einen Entschlüssler schreiben.

    Leider ist die Doku nicht vollständig und ich will nicht von einem Compiler abhängen.

    Was sagt der Standard eigentlich genau über den Namen? ich meine da kann doch nicht einfach irgendetwas drin stehen darf. Von irgendetwas muss man doch schon ausgehen können, oder?



  • Hi,

    ich bin irgendwie verwirrt! ich dachte new wäre etwas eigenständiges und würde nicht auf ANSI C zurückgreife, doch da hab ich mich wohl geirrt...

    // newop operator new(size_t) for Microsoft C++
    #include <cstdlib>
    #include <new>
    
    _C_LIB_DECL
    int __cdecl _callnewh(size_t size) _THROW1(_STD bad_alloc);
    _END_C_LIB_DECL
    
    void *__cdecl operator new(size_t size) _THROW1(_STD bad_alloc)
    	{	// try to allocate size bytes
    	void *p;
    	while ((p = malloc(size)) == 0)
    		if (_callnewh(size) == 0)
    			_STD _Nomemory();
    	return (p);
    	}
    
    /*
    * Copyright (c) 1992-2001 by P.J. Plauger.  ALL RIGHTS RESERVED.
     * Consult your license regarding permissions and restrictions.
     V2.3:0009 */
    

    Auf den code bin ich gestoßen als ich bei .NET mit dem Debugger hantiert habe.



  • Unwissender schrieb:

    Naja wenn es mit typeid geht ist das das Rad neuerfunden.

    Es geht ja eben nicht, sonst hättest du das Problem ja nicht.

    Es heist, dass es besser ist Preprocessor Instruktionen zu vermeiden, allerdings mit Prepreprocessor Instruktionen hab ich noch keine Erfahrung 🙄 .

    Ich red ja auch nicht von DEM Preprozessor, deshalb steht da das Wort "eigener". Aber diese Möglichkeit fällt dann wohl aus 🙄

    Was sagt der Standard eigentlich genau über den Namen? ich meine da kann doch nicht einfach irgendetwas drin stehen darf. Von irgendetwas muss man doch schon ausgehen können, oder?

    18.5.1 sagt: «an implementation-defined value»
    Schlechte Karten für eine portable Lösung, schätze ich.



  • 18.5.1 sagt: «an implementation-defined value»
    Schlechte Karten für eine portable Lösung, schätze ich.

    Tja dann muss ich das wohl irgendwie anders machen 😞

    Ich red ja auch nicht von DEM Preprozessor, deshalb steht da das Wort "eigener". Aber diese Möglichkeit fällt dann wohl aus

    Ich bin ja auch nicht kategorisch gegen Prepreprocessor, nur finde ich, dass es übertrieben ist beim kleinsten Syntaxproblem die radikalste aller Lösungen zu nehmen.

    Ich werde dann halt eine Basis Klasse machen die eine virtuelle Funktion hat.


Anmelden zum Antworten