ist das standard?



  • ich hab mich die letzten Tage mal gefragt, ob es eine Möglichkeit gibt, polymorphie zu realisieren, ohne gleichzeitig die nachteile in Kauf nehmen zu müssen.

    ich hab jetzt dazu mal einen experimentellen testcode laufen lassen, in der überzeugung, dass der abstürzen würde, aber das tat er wieder erwarten nicht. nun bin ich en bissl perplex, ist das am ende vielleicht sogar standard?

    basisklasse:

    template<class T>
    struct Foo{
    	void doSth(){
    		static_cast<T* const>(this)->do_Sth();//soll abstürzen
    	}
    
    };
    

    abgeleitete Klasse:

    struct Bar:public Foo<Bar>{
    	void do_Sth(){
    		std::cout<<"ich lebe noch";
    	}
    };
    

    testfunktion:

    template<class T>
    void foobar(Foo<T>& foo){
    	foo.doSth();
    }
    

    ausgabe: ich lebe noch

    da ich dem nicht geglaubt hab, hab ich das nochmal mit mehrfachvererbung etc ausprobiert, ich hab alles dran gesetzt, das zum absturz zu bringen, aber es klappte nicht. 😃



  • Der Sinn erschließt sich mir nicht.

    struct Bar:public Foo<Bar>
    struct Baz:public Foo<Baz>
    

    Die haben ja jetzt keine gemeinsame Basisklasse. Wie verwaltest du die Objekte die du polymorph aufrufen willst?



  • otze schrieb:

    testfunktion:

    template<class T>
    void foobar(Foo<T>& foo){
    	foo.doSth();
    }
    

    dazu brauchst du die Basisklasse nicht:

    template<class T>
    void foobar(T& foo) { foo.doSth(); }
    


  • Die haben ja jetzt keine gemeinsame Basisklasse. Wie verwaltest du die Objekte die du polymorph aufrufen willst?

    mithilfe von funktionen wie foobar. ich muss bestimmte arten von Klassen komplett anders betrachten als andere,will aber den virtual overhead draussen haben(es geht hierbei nicht ums polymorphe abspeichern, sondern ums polymorphe ansprechen)

    aber eigentlich ist es nur ein "weil es möglich ist"

    DrGreenthumb schrieb:

    dazu brauchst du die Basisklasse nicht:

    template<class T>
    void foobar(T& foo) { foo.doSth(); }
    

    Nein. Wirklich? 😃 hätt ich nie geglaubt! 🤡



  • otze schrieb:

    DrGreenthumb schrieb:

    dazu brauchst du die Basisklasse nicht:

    template<class T>
    void foobar(T& foo) { foo.doSth(); }
    

    Nein. Wirklich? 😃 hätt ich nie geglaubt! 🤡

    ist das jetzt Ironie oder die Freude dass sich deine Frage dadurch erledigt hat?



  • DrGreenthumb schrieb:

    ist das jetzt Ironie oder die Freude dass sich deine Frage dadurch erledigt hat?

    ironie.

    es gibt natürlich eine funktion foobar(const T&), dies ist nur eine überladung, da es nicht überall so geht.

    (wär aber froh, wenn man unabhängig des nutzfaktors wieder zurück zum topic gehen könnte, das intressiert mich jetzt mal wirklich^^)



  • Hallo,
    das ist nicht nur legal sondern soweit verbreitet, dass dieses Idiom sogar einen Namen hat: Curiously Recurring Template Pattern. Kurz CRTP.

    Es gibt viele verschiedene Versionen des Patterns und hunderte sinnvolle Anwendungsgebiete. Ein Beispiel für die Benutzung dieser Form der statischen Polymorphie ist die Implementation einer 3-Level Finite-State-Machine. Ein anderes die Implementation des Typed Message Patterns.
    Weitere Beispiele findest du z.B. in vielen boost-libs.





  • Microsofts ATL/WTL verwenden dieses Muster exzessiv. 🙂



  • könnte man mit dieser Technik nicht das iteratorkonzept der STL grundlegend verändern?

    zb beim beispiel eines iterators bei einem vector:

    class VectorIterator:public RandomAccessIterator<VectorIterator>{
        //...
    };
    

    wenn jetzt eine funktion einen randomacces iterator braucht, macht sie einfach sowas:

    template<class T>
    void foo(const RandomAccessIterator<T>&){...}
    

    wenn ich mir meine stl implementation anschau, steht da bisweilen sowas:

    template<typename _RandomAccessIterator, typename _OutputIterator>
        inline _OutputIterator __copy(_RandomAccessIterator __first, _RandomAccessIterator __last,
    	   _OutputIterator __result, random_access_iterator_tag)
    

    wär das nicht eine verbesserung? Ok, die Frage wäre,was man mit normalen zeigern machen sollte...


Anmelden zum Antworten