Klassentemplate: Nur einzelne Methoden spezialisieren



  • Hmmm, nun, das wird zwar etwas kürzer, aber so richtig zufrieden bin ich damit nicht. Fällt irgendwie unter den Begriff "frickeln" 😉 Ich benutze schon BOOST_STATIC_ASSERT() um Methoden, die nur mit m==n funktionieren zu definieren. Aber die selben Methoden für m==n==3 und m==n==2 müssen ja auch definiert werden und da liegt der Hund begraben. Eigentlich müsste man nur die spezialisieren, aber das geht nicht partiell. Ich kann wirklich nicht glauben, dass da sonst keiner dran gedacht hat. Oder ist meine Matrix-Klasse selbst schrottig? Wie auch immer, ich lasse das mal ruhen und komme wieder darauf zurück, wenn ich Muse habe. Ich finde es aber trotzdem schön, dass du dir Gedanken darüber machst, sonst wäre ich längst zu der Erkenntnis gelangt, dass ich einfach zu blöd dafür bin 😉


  • Mod

    geloescht schrieb:

    Aber die selben Methoden für m==n==3 und m==n==2 müssen ja auch definiert werden und da liegt der Hund begraben.

    Das geht doch ebenso einfach:

    template<typename T, int n>
    class basic_matrix<T, n, n, true>
    // ...
    

    so hast du zwar auch ein template wenn m,n nicht 2 oder 3 ist, aber dieses wird ja dank des bools im Regelfall nicht instantiiert.



  • öhm. Verstehe nicht. Wie kommen dann die zwei Methoden rein? Die sind ja für 2 und drei unterschiedlich.


  • Mod

    unterscheiden sich die Funktionen nur in ihrer Implementation?



  • Ja, und eben in der Klasse, der sie angehören.


  • Mod

    geloescht schrieb:

    Ja, und eben in der Klasse, der sie angehören.

    Dann ist das Problem weitaus einfacher zu lösen, als du anfangs dargestellt hast.
    per SFINAE:

    template<typename T, int m, int n>
    class basic_matrix
    {
    public:
    //    void foo(); wird zu
        typename enable_if_c<m!=m||m!=2&&m!=3,void>::type foo(); // der allgemeine Fall
        typename enable_if_c<m==n&&m==2,void>::type foo(); // m,n == 2
        typename enable_if_c<m==n&&m==3,void>::type foo(); // m,n == 3
    // usw.
    };
    

    Es gibt noch ein paar andere Möglichkeiten, das mittes enable_if zu machen , ich verweise dazu auf die Boost Doku

    Eine andere Möglichkeit:

    template<typename T, int m, int n>
    class basic_matrix
    {
    private:
        template<typename U=T,int o=m,intp=n> friend class DoFoo;
    public:
        void foo() { DoFoo<>()(this); }
    };
    
    template<typename T, int m, int n> class basic_matrix::
    template<typename U, int o, int p> class DoFoo
    {
        void operator()(basic_matrix<T,m,n>*) { /* ... */ }
    };
    
    template<typename T, int m, int n> class basic_matrix::
    template<> class DoFoo<T,2,2>
    // usw.
    

    Indirektion löst noch (fast) jedes Problem.



  • Wahrscheinlich wusste ich nicht, wie ich es anfangs so darstellen konnte, dass man es so lösen könnte 😉
    Das eröffnet neue Horizonte für mich. Auch wenn es wirklich seltsam aussieht. Dankeschön. Wenn ich das ganze wie in der Doku vorgeschlagen als Default-Parameter vom Typ void* mache dann wird der Parameter doch hoffentlich rausoptimiert, wenn ich ihn nicht benutze.



  • darf ich fragen warum du das nicht einfach mit ner if bedingung löst ?



  • Weil Templates zur Compilezeit erstellt werden und ifs zur Laufzeit ausgeführt werden. Außerdem wäre ein if unübersichtlich und etwas langsamer in der Ausführung, was ich nicht will, weil es um ein 3D-Renderingprogramm geht.



  • Ob das jetzt für dich sinnvoll ist oder nicht sei mal dahingstellt, dennoch es ist durchaus möglich relativ leicht if-Statments mit Hilfe von Templates nachzubilden.

    Hier mal ein Beispiel von: http://www.lrz-muenchen.de/~ebner/C++/Slides/cxxkurs.html

    // Klassendeklaration:
    template<bool C>
    class IfThen { };
    
    // Spezialisierung für beide Fälle
    class IfThen<true> {
      public:
        static inline void f()
        { statement1; }
    };
    
    class IfThen<false> {
      public:
        static inline void f()
        { statement2; }
    };
    
    // Ersatz des 'if/else'-Statements:
    IfThen<condition>::f();
    

    Gruß Baracke


Anmelden zum Antworten