templates



  • Wer macht denn solche Tutorials? Keine Referenzen werden genutzt ➡ Worst Case wird da kopiert!



  • ty pumuckl. da ich nur zahlendatentypen in das funktions template übergeben würde, würde wohl ein vergleichsoperator existieren, trotzdem ganz interessant zu sehen wie du es mit den stuct vergleichen gemacht hast.

    problem ist dass ich nicht einfach konvertieren kann und das ganze wohl doch etwas komplizierter wird weil ich möglicherweise präzise => unpräzise konvertiere und daten verloren gehen. (T unpräzise, U präzise).

    habe dein beispiel aber noch nicht ganz verstanden, was passiert in den folgenden zeilen am besten befehl für befehl.

    struct B {
      int i;
      B(A const& a) : i(a.i) {}
      B(int i) : i(i) {}
    };
    

    EOutOfResources schrieb:

    Wer macht denn solche Tutorials? Keine Referenzen werden genutzt ➡ Worst Case wird da kopiert!

    http://www.cplusplus.com/doc/tutorial/templates/



  • Halozination schrieb:

    hi, lese gerade ein tutorial durch indem folgendes vorkommt:

    template <class T, class U>
    T GetMin (T a, U b) {
      return (a<b?a:b);
    }
    

    Wenn ich nun Die funktion getmin mit 2 verschiedenen typen T und U aufrufe kann sie doch nur einen typen T returnen? also wenn b returnt werden soll sollte es eigentl. nicht mögl sein (mit korrektem typ)?

    weitere Aufgabe: dekliniere return:
    ich returne / du returnst / er,sie,es returnt / wir returnen / ihr returnt / sie returnen



  • return ist ein Verb, das wird also konjugiert.



  • [Klugscheißen]Ja, da aber to return zweifelsohne aus dem Englischen kommt, müsstest du es dann auch nach englischen Regeln konjugieren. Da das aber komisch klingt, vermeidet man das einfach und benutzt das deutsche Wort: zurückgeben. ;)[/Klugscheißen]



  • Halozination schrieb:

    habe dein beispiel aber noch nicht ganz verstanden, was passiert in den folgenden zeilen am besten befehl für befehl.

    Das ist eine Typdefinition für einen Datentyp mit einem (öffentlich zugänglichen) int-Element und zwei Konstruktoren. Der erste Konstruktor übernimmt eine andere Struktur und wird bei der Parameter-Umsetzung für den Vergleichsoperator genutzt (um aus dem an die GetMin() übergebenen A ein B zu machen), der zweite für die Initialisierung des B myB in der main().

    PS: Um dieses Template so zu erweitern, daß es den "besseren" der beiden Template-Parameter zurückgibt, benötigst du vermutlich tiefere Kenntnisse in Template-Metaprogrammierung. Obwohl, eventuell lässt sich in C++0x mit decltype() etwas derartiges ausdrücken.


  • Mod

    könnte z.B. so aussehen (ungetested):

    template <typename T, typename U>
    struct select_best : boost::mpl::if_c<
        std::numeric_limits<T>::is_specialized
            && std::numeric_limits<U>::is_specialized
            && std::numeric_limits<T>::is_exact == std::numeric_limits<U>::is_exact
            && std::numeric_limits<T>::is_signed == std::numeric_limits<U>::is_signed,
        boost::mpl::if_c<
            std::numeric_limits<T>::is_signed,
            boost::mpl::if_c<
                std::numeric_limits<T>::digits < std::numeric_limits<U>::digits,
                U,
                T>,
            boost::mpl::if_c<
                std::numeric_limits<U>::digits < std::numeric_limits<T>::digits,
                U,
                T> >,
        void >
    {};
    
    template <typename T, typename U>
    typename select_best<T,U>::type GetMin(T a, U b)
    {
        typedef typename select_best<T,U>::type result_type;
        sizeof( result_type );
        return b < a ? static_cast<result_type>( b ) : static_cast<result_type>( a );
    }
    


  • CStoll schrieb:

    PS: Um dieses Template so zu erweitern, daß es den "besseren" der beiden Template-Parameter zurückgibt, benötigst du vermutlich tiefere Kenntnisse in Template-Metaprogrammierung. Obwohl, eventuell lässt sich in C++0x mit decltype() etwas derartiges ausdrücken.

    decltype wird da auch nicht helfen, man braucht so oder so ein genauigkeit-vergleichendes type-trait, und wenn man das hat ist decltype auch nicht mehr nötig.



  • Ich erlaube mir mal ganz themenfremd zu sagen: „Jodocus, sie sind raus!“ 😉



  • ok pumuckl habe mir geraden och einmal dein beispiel mit erklärung durchgelesen und glaube nun versteh ich es, echt ziemlich verrückt. Der compiler macht also aus myA ein B und myB ein C (ohne es ihm zu sagen) weil er sonst den < operator nicht ausführen kann und desshalb muss diese anderen constructor dabei haben

    B(A const& a) : i(a.i) {}
    

    . man könnte es dem compiler aber eigentl auch sagen oder den vergleich direkt für A und B structs erstellen 😃

    noch eine frage:

    B struct = i von der ursprüngl. 
    [cpp]
    struct B {
      int i;
      B(int i) : i(i) {} //ich hätte geschrieben B(int j) {i = j} 
    };
    ... 
    B myB = 12; //myB (myB (12)
    

    Was genau bedeutet ":" nach dem constructor? ich betrachte constructoren nur als funktion und deine schreibweise tut was genau? i(i) sieht für mich zieml. verwirrend aus.



  • Halozination schrieb:

    ok pumuckl habe mir geraden och einmal dein beispiel mit erklärung durchgelesen und glaube nun versteh ich es, echt ziemlich verrückt. Der compiler macht also aus myA ein B und myB ein C (ohne es ihm zu sagen) weil er sonst den < operator nicht ausführen kann und desshalb muss diese anderen constructor dabei haben

    Ja, das sind einige Dinge, die da zusammenfinden. Was mein Beispiel eigentlich verdeutlichen sollte: der Compiler nimmt die beiden Typen, die er ja aus der Substitution der Templateparameter kennt, und versucht damit die Ausdrücke im Template zu compilieren.
    Wenn er auf den operator< trifft (oder allgemein auf irgendeine Funktion), und die Argumenttypen passen nicht exakt zu einer Funktion, die es schon gibt, dann fängt er an, durch implizite Konvertierungen an den Typen rumzubiegen, bis er einen passenden Satz gefunden hat, der zu einer bestehenden Funktionssignatur passt. Das tut er übrigens nicht nur bei Templates, sondern eigentlich immer. Beispiel:

    int foo(int);
    short s;
    foo(s); //der compiler findet kein foo(short), aber short kann er ja in int konvertieren...
    

    Halozination schrieb:

    man könnte es dem compiler aber eigentl auch sagen oder den vergleich direkt für A und B structs erstellen 😃

    klar könnte man. Aber man muss es ihm nicht direkt sagen, denn er kanns ja implizit machen. Das Beispiel zeigt übrigens eine der großen Gefahren von impliziten Konvertierungen, d.h. von Konstruktoren, die ein Argument haben und nicht als explizit deklariert sind, sowie von Konvertierungsoperatoren: Stell dir vor, A, B, C seien Bestandteile einer Bibliothek. Ein Anwender der Bilbiothek benutzt As und Bs in seinem Code und kennt vielleicht nichtmal das Interface von C, weiß also auch nichts von dem op<. Er vertippt sich und schreibt b<a - der Compiler schluckt das anstandslos, konvertiert wild an den Argumenten rum und macht einen Vergleich von dem der Entwickler nichtmal wusste dass er existiert. Sicher nicht das, was der Entwickler vorhatte...

    Halozination schrieb:

    noch eine frage:

    B struct = i von der ursprüngl. 
    [cpp]
    struct B {
      int i;
      B(int i) : i(i) {} //ich hätte geschrieben B(int j) {i = j} 
    };
    ... 
    B myB = 12; //myB (myB (12)
    

    Was genau bedeutet ":" nach dem constructor? ich betrachte constructoren nur als funktion und deine schreibweise tut was genau? i(i) sieht für mich zieml. verwirrend aus.

    Stichwort: initialisierungsliste. Ist dazu da, um Member und Basisklassen zu initialisieren, d.h. deren Konstruktoren aufzurufen.
    Zugegegeben, hier siehts etwas verwirrend aus. Die Zeile könnte auch heißen

    B(int iArg) : i(iArg) {}
    

    - das bedeutet, dass der Member i mit dem iArg initialisiert wird.


Anmelden zum Antworten