Templates



  • lese gerade den artikel in eurem magazin

    und da stellt sich folgende frage

    die template-funktion:

    template <typename T>
    inline const T& minimum(const T &a, const T &b) {
      return a < b ? a:b;
    };
    

    wieso darf man

    // Verstehe ich
      int z = minimum<int>(x,y);
      std::cout<<z<<'\n';
      char a = 'a', b = 'b';
      // Wieso gibt er hier keinen template-parameter an?
      std::cout<<minimum(a,b)<<'\n';  //Gibt a aus
    

    (die frage ist im code als kommentar)

    danke im voraus



  • Weil der Compiler die template-Parameter aus den Übergabeparametern bestimmen kann.
    Das läuft ungefähr so: Der Compiler trifft beim Parsen auf den Ausdruck minimum(a,b). Der Compiler kennt zu diesem Zeitpunkt bereits die Deklaration von minimum. a ist ein char, also muss der erste Übergabeparameter ein char sein, also muss T=char sein. b ist ebenfalls ein char und da T ja bereits ein char ist passt auch der zweite Übergabeparameter.



  • verstehe

    das heißt dass ich bei den funktionsaufrufen den template-parameter nicht angeben muss?

    vielen dank für deine erklärung!



  • Ja, im Allgemeinen kannst du den template-Parameter weglassen.



  • 👍 danke!



  • Wenn der Compiler sich das aus den Parametern, die Du der Funktion übergibst, selbst ableiten kann dann muss man das nicht mit angeben. Das klappt aber nicht immer: Gegenbeispiele:

    template<class R, class T, class U>
    R add(T t, U u)
    {
      R r = t;
      t += u;
      return r;
    }
    
    …
    add<double>(2,3);
    

    (Man muss R angeben, T und U können automatisch bestimmt werden)

    template<class T>
    T add2(T t, T u)
    {
      return t+u;
    }
    
    …
    add(2,3.3); // Klappt nicht!
    

    denn nach dem ersten Parameter würde T=int gelten. Aber dem zweiten Parameter zufolge käme der Compiler auf T=double. In so einem Fall schlägt die "template argument deduction" einfach fehl. Wenn Du allerdings add<double>(2,2.3) oder add(2.0,3.0) schreibst, klappt es wieder. Das Misslingen der "Template Argument Deduction" ist übrigens kein "harter" Fehler. Das Funktionstemplate wird dann einfach ignoriert. Nur wenn keine passende Funktion übrig bleibt, meckert der Compiler. Manchmal kann es sinvoll sein, "TAD" für einen Parameter auszuschalten. Das geht über einen Trick:

    template<class T> struct identity{typedef T type;};
    
    template<class T>
    struct punkt
    {
      T x, y;
    };
    
    // template<class T>
    // punkt<T> operator*(punkt<T> const& p, T faktor);
    
    template<class T>
    punkt<T> operator*(punkt<T> const& p, typename identity<T>::type faktor);
    //                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
    

    Obwohl aus identity<T>::type wieder T selbst wird, stellt es einen sogenannten "non-deduced context" dar. Das heißt, der Compiler verwendet diesen Parameter nicht, um T rauszubekommen.

    kk


Log in to reply