type_info::name für unterschiedliche Klassen immer verschieden?
-
Eric Cartman schrieb:
wie kommen die GCC-Hersteller auf diese Namen?
Das sind glaube ich die Linkersymbole.
Im Allgeminen finde ich typeid ziemlich nutzlos. Eventuell kann der Threadstarter folgenden Trick gebrauchen:
unsigned make_id(){ static unsigned id = 0; return id++; } template<class T> unsigned get_type_id(){ static unsigned id = make_id(); return id; }Um typeid und type_info gehört meiner Meinung nach einen großen Bogen gemacht.
-
typeid schrieb:
ich kann leider type_info nicht in einem vektor o.ä. speichern (copy-konstruktor und zuweisung sind private), sondern nur das, was type_info::name zurückliefert. genau das bräuchte ich für die serialisierung, ich gehe schon einen umweg über nummern (um die compiler-abhängigen namen zu vermeiden), aber wenn ich mich nicht mal auf oben genannte bedingung verlassen kann ist das schon schade...

Wie wäre es, wenn du
std::type_infokapselst?#include <typeinfo> class TypeInfo { // Attributes // private: std::type_info const* m_type; // Constructors // public: TypeInfo(std::type_info const& type) : m_type(&type) { } // Methods // public: std::type_info const& get_type() const { return *m_type; } }; bool operator ==(TypeInfo const& lhs, TypeInfo const& rhs) { return lhs.get_type() == rhs.get_type(); } bool operator !=(TypeInfo const& lhs, TypeInfo const& rhs) { return lhs.get_type() != rhs.get_type(); } bool operator <(TypeInfo const& lhs, TypeInfo const& rhs) { return lhs.get_type().before(rhs.get_type()); }Oder irgendetwas in diese Richtung ...
Grüssli
-
@ben04: hmm, schaut schon mal gut aus. jetzt brauche ich nur noch einen trick, wie ich die "echte" klassen-id von einem objekt bekomme, auf das ich über einen basisklassenzeiger zugreife. ich möchte nicht für jede abgeleitete klasse eine methode überschreiben, die eigentlich doch immer das gleiche tut:
class base { //... public: virtual unsigned int get_class_id() const {return get_type_id<base>();} }; class derived : public base { //... public: virtual unsigned int get_class_id() const {return get_type_id<derived>();} };das muss doch auch irgendwie eleganter gehen, oder? schließlich kann es schnell passieren, dass man das überschreiben der methode mal vergisst...

-
Folgendes geht:
class Base{ public: virtual unsigned get_id()const=0; }; template<class T> class DeriveFromBase:public Base{ public: virtual unsigned get_id()const{ return get_type_id<T>(); } }; class Child:public DeriveFromBase<Child>{ };Dadurch, dass man this nach T* in DeriveFromBase castet kann man noch viele schöne Sachen machen. Zum Beispiel eine Clonefunktion welche den (möglicherweise implizit erzeugten) Kopiekonstruktor der Kindklasse verwendet.
Alternativ kann man auch eine Makro DEFAULT_METHODS definieren und in jede Childklasse reinpacken. Dieser Ansatz erlaubt es zusätzlich den Klassennamen portabel aber nicht eindeutig in einen String zu kriegen.
-
Dravere schrieb:
TypeInfo(std::type_info const& type) : m_type(&type) { }hmm, hier sehe ich das problem, dass der zeiger zu einem späteren zeitpunkt ins leere verweisen kann, nämlich nachdem der block verlassen wurde, in dem dieser konstruktor aufgerufen wurde. oder garantiert mir der standard, dass die adresse des von typeid zurückgegebenen objektes immer gültig bleibt? wäre schön...
-
C++ Standard 98:
Kapitel 5.2.8 Type Identification
Abschnitt 1The result of a typeid expression is an lvalue of static type
const std::type_info(18.5.1) and dynamic typeconst std::type_infoorconstname where name is an implementation-defined class derived fromstd::type_infowhich preserves the behavior described in 18.5.1. The lifetime of the object referred to by the lvalue extends to the end of the program. Whether or not the destructor is called for thetype_infoobject at the end of the program is unspecified.Grüssli
-
Du kannst auch gleich Boost.Pointer Container verwenden, die stellen keine Anforderungen bezüglich Kopierbarkeit. Oder Standardcontainer mit
shared_ptr.
-
Nexus schrieb:
Du kannst auch gleich Boost.Pointer Container verwenden, die stellen keine Anforderungen bezüglich Kopierbarkeit. Oder Standardcontainer mit
shared_ptr.Welche dann ein
deleteauf den Zeiger vonstd::type_infodurchführen. Huiiiii, schöööönes Feuerwerk
Ok, beimshared_ptrkönnte man das abschalten. Aber der Overhead vomshared_ptrist völlig unnötig. Es muss keine Referenzzählung stattfinden. Die Verwendung von Boost.PtrContainer oder Boost.SmartPointer ist hier völlig fehl am Platz.Grüssli
-
Oh sorry, ich hab deinen Beitrag vorhin zu wenig genau gelesen...
Dann sollte es eigentlich auch ein einfacher Zeiger tun, oder?
-
Nexus schrieb:
Dann sollte es eigentlich auch ein einfacher Zeiger tun, oder?
Ja, nur hast du dann Probleme diesen Zeiger zu vergleichen. Es ist nicht garantiert, dass immer das gleiche Objekt für den gleichen Typen zurückgeliefert wird. Der Vergleich muss also über das Objekt gehen, auf welches der Zeiger zeigt. Dafür ist eben der Wrapper da.
Grüssli
-
Ja, der Wrapper ist halt bequem anzuwenden, weil du dir das Zeiger-Dereferenzieren sparen kannst.

Aber die Lebensdauer von
std::type_info-Objekten ist schon etwas merkwürdig. Ich hätte nicht gedacht, dass die so eine Ausnahme darstellen. Das lädt ja direkt zu Memory Leaks ein...
-
Nexus schrieb:
Das lädt ja direkt zu Memory Leaks ein...
Ist glaube ich sogar legal, nur macht das keiner. In der Regel gibt es genau ein type_info Objekt per Typ und in jede vtable wird ein Zeiger darauf reingepackt. Wenn Dlls ins Spiel kommen, dann kann es mehrere type_info Objekt per Typ geben. Halt einen in jedem Modul. Da der Standard keine Dlls kennt greift er halt auf eine so wage Formulierung zurück.
-
Dravere schrieb:
C++ Standard 98:
Kapitel 5.2.8 Type Identification
Abschnitt 1The result of a typeid expression is an lvalue of static type
const std::type_info(18.5.1) and dynamic typeconst std::type_infoorconstname where name is an implementation-defined class derived fromstd::type_infowhich preserves the behavior described in 18.5.1. The lifetime of the object referred to by the lvalue extends to the end of the program. Whether or not the destructor is called for thetype_infoobject at the end of the program is unspecified.Grüssli
okay, vielen dank!
die lebensdauer der rückgabe von typeid hat mich doch etwas irritiert, aber damit wäre das problem jetzt für mich gelöst. die idee mit dem template von ben04 ist auch nicht schlecht, aber so ist das vorerst doch etwas unkomplizierter. 