"Radikales Casten"



  • Hallo,

    gibt es irgendeine Methode, mit der man versuchen kann, zwei beliebige Zeigertypen ineinander zu casten? Der Cast sollte sich wie ein dynamic_cast verhalten, aber keine Fehlermeldung beim Kompilieren bringen, wenn der Quelltyp nicht polymorph ist. In diesem Fall sollte dann einfach ein Nullzeiger dabei herauskommen.

    Beispiel:

    class A
    {
    public:
    };
    
    class B : public A
    {
    public:
    };
    
    A* a = new B;
    radical_cast<B*>(a) == 0; // Hier käme bei dynamic_cast die Fehlermeldung.
    
    class Ap
    {
    public:
    	virtual ~Ap() { }
    };
    
    class Bp : public Ap
    {
    public:
    };
    
    Ap* ap = new Bp;
    radical_cast<Bp*>(ap) != 0; // Das sollte klappen.
    

    Zumindest theoretisch sollte das doch machbar sein, da der Compiler ja schon erkennt, dass der Cast ungültig ist. Was ich will, ist, dass er dann aber keine Fehlermeldung ausgibt, sondern einfach einen Nullzeiger zurückliefern lässt. Dass das so direkt nicht geht, ist mir klar, aber vielleicht gibt es ja irgendetwas Boost-artiges für dieses Problem.

    Hintergrund ist natürlich eine Template-Geschichte.
    Ich möchte im Template herausfinden, ob die verwendete Klasse von einer bestimmten anderen Klasse erbt (direkt oder über mehrere Ebenen). Dafür brauche ich diesen Cast.
    Oder gibt es einen Weg, ein Template so zu spezialisieren, dass es immer dann verwendet wird, wenn der verwendete Typ von einer bestimmten Klasse erbt?

    Für einen Lösungsansatz wäre ich sehr dankbar.



  • In boost gibt es polymorphic_cast und polymorphic_downcast.
    Kommt natürlich ganz darauf an was Du mit deinem Algorithmus erreichen willst.
    Für bestimmte Zwecke findet auch der Visitor pattern sein Anwendungsgebiet.

    WX



  • TomasRiker schrieb:

    Oder gibt es einen Weg, ein Template so zu spezialisieren, dass es immer dann verwendet wird, wenn der verwendete Typ von einer bestimmten Klasse erbt?

    Für Funktionstemplates sollte so etwas möglich sein, für Klassentemplates aber habe ich da bisher nur seltsame Konstrukte gesehen, die sizeof() auf den Rückgabetyp einer mit einem Parameter aufgerufenen Funktion als konstanten Ausdruck verwendeten. Wenn dein Compiler so etwas schluckt, geht es vermutlich.

    Edit: Würde dir so etwas helfen?

    template <typename Base>
    	bool isBaseClass (Base* ptr)
    { return true; }
    template <typename Base>
    	bool isBaseClass (void* ptr)
    { return false; }
    
    class Base { };
    class Derived : public Base { };
    class NotDerived { };
    
    int main (void)
    {
    	Derived* d = new Derived;
    	NotDerived* nd = new NotDerived;
    
    	isBaseClass <Base> (d) == true;
    	isBaseClass <Base> (nd) == false;
    }
    

  • Mod

    Die Aufgabe ist unzureichend spezifiziert. Im Übrigen sagt dir auch dynamic_cast nicht, ob eine Klasse von einer anderen erbt, sondern nur, ob das vollständige Objekt, auf das gezeigt wird, von beiden erbt bzw. mit diesen identisch ist - Stichwort cross-cast.



  • Danke, es hat sich erledigt.
    Der Ansatz von audacia war das, was ich gebraucht hatte.
    Manchmal ist die Lösung eben ganz simpel 🙂

    Und ja, dynamic_cast war gar nicht das, was ich meinte ... sorry!


  • Mod

    boost::is_convertible<T*,U*> tut es auch


Anmelden zum Antworten