Template Funktion - Defintion der Typen, ohne dass sie in den Parametern auftauchen



  • Hallo zusammen!
    Ich habe mal wieder eine Frage :).

    Es besteht folgende (minimierte) Problematik:
    ---------------------------------------------------------------------------
    Die Template-Funktion:
    ...
    template <class T1 , class T2>
    void dieFunktion(T1 wert)
    {
    T2 a = new T2(wert);
    }

    Der ausführende Code (z.B. mit bool)
    ...
    dieFunktion< bool , KlasseX > ( true );

    (Läuft nicht)
    ---------------------------------------------------------------------------
    Normalerweise kann man sich die spitzen Klammern ja sparen, wenn durch die Parameter der Funktion klar ist, um welche Typen es sich handelt.

    Die Fragestellung ist also: Wie ist bitte der Syntax um Template Platzhalter zu verwenden, die nicht durch einen Parameter der Funktion definiert werden?

    Beste Grüße,
    Oliver


  • Mod

    Doch, das ist richtig. Wenn du mehr sagen würdest als "läuft nicht" könnte man dir sogar helfen.

    Einen Fehler kann man sogar sofort sehen:

    T2 a = new T2(wert);
    

    Dies kann nur in Ausnahmenfällen funktionieren, da new einen T2* zurückgibt, welcher im Allgemeinen nicht kompatibel zu einem T2 sein wird. Das sollte dir dein Compiler aber auch eigentlich sagen, wenn das Template instanziert wird (und das wird es in deinem Beispiel).



  • nenn die template-parameter, die aus den parametern geschlossen werden können, als letzte in der liste. dann kannst du sie weglassen beim konkreten aufruf. falls ich dein problem jetzt richtig verstanden habe.

    ru,
    cirion



  • Hehe .. "T2 a = new T2(wert);" spielt keine Rolle sorry. Das entstammt nicht dem Quellcode, sondern meinem minimierten Beispiel hier.

    (Vielen Dank für die schnellen Reaktionen übrigens)

    Ich mache nochmal ein Beispiel, evtl. wird deutlicher was ich meine.

    -- Beispiel 1 - läuft ------------------------------

    Die Funktion:

    template <class T1>
    void dieFunktion(T1 wert)
    {
    //Mache irgendwas mit wert
    }

    Aufruf der Funktion:

    dieFunktion(IrgendEinWert);
    ******************************************************
    Hier ist alles ohne Probleme! T1 wird definiert durch die Übergabe des Parameters der Funktion.
    Alternativ hätte ich die Funktion auch wie folgt aufrufen können (z.B. für bool):

    dieFunktion<bool>(IrgendeinBoolscherWert).

    Das läuft auch!

    -- Beispiel 2 - läuft nicht --------------------------

    Die Funktion:

    template <class T1, class T2>
    void dieFunktion(T1 wert)
    {
    //Mache irgendwas mit (T1)wert und irgendwas mit dem Typ T2
    }

    Aufruf der Funktion:
    dieFunktion(IrgendEinWert); // DAS GEHT JA NICHT MEHR! Weil T2 damit nicht definiert ist.

    Also mache ich den Aufruf wie folgt (z.B. für bool):

    dieFunktion < bool , IrgendeineKlasse > (IrgendEinWertBoolscherWert);

    ------------------------------------------------------

    Der Compiler bemängelt hier, dass er keine Übereinstimmung finden kann. D.h. ich mache wohl irgendwas falsch.

    Ich versuchs nochmal Konkret : Ich muss einen Template Parameter entsprechend erzeugen können ohne, dass er als Übergabeparamter in einer Funktion steht.



  • dein beispiel nr. 2 funktioniert eigentlich völlig problemlos bei mir - da hast du beim reduzieren des problems wohl die fehlerquelle wegreduziert.

    ru,
    cirion


  • Mod

    Doch, das ist richtig! Dein Beispiel läuft, zumindest nachdem man int main() und so ergänzt hat.

    Bring bitte mal ein vollständiges Minimalbeispiel, welches den Fehler zeigt, aber ansonsten compilierbar ist. Und die genaue Fehlermeldung.



    • Benutze bitte [cpp]-Tags (erste weisse Schaltfläche).
    • Schreibe ein komplettes Minimalbeispiel ohne Kompilierfehler, die nichts mit dem Problem zu tun haben, hin.
    • Poste die exakte Fehlermeldung des Compilers.

    Nur so können wir sicher sein, dass die Vereinfachung nicht das Problem ist, und können auf Spekulationen verzichten.



  • Roger!

    Hab das Problem gelöst. Ihr habt recht. Ich habs weg-minimalisiert.

    Vielen Dank trotzdem und bis zur nächsten Frage.

    Beste Grüße,
    Oliver



  • Wenn du bool vewenden möchtest, dann muss der erste Typ ein typename
    sein und keine class

    template <typename T1 , class T2> 
    void dieFunktion(T1 wert) 
    { 
    T2 a = new T2(wert); 
    }
    

    Gruß,
    CSpille



  • CSpille schrieb:

    ...

    Das ist nicht korrekt wenn ich mich richtig erinnere.
    class und typename sind in diesem Kontext gleichwertig und austauschbar.

    Simon



  • Oh...

    Nehm alles zurück...



  • theta schrieb:

    CSpille schrieb:

    ...

    Das ist nicht korrekt wenn ich mich richtig erinnere.
    class und typename sind in diesem Kontext gleichwertig und austauschbar.

    Simon

    Ehrlich gesagt bin ich jetzt etwas verwirrt...
    Unter welcher Bedingung sind sie denn austauschbar?

    Bisher habe ich für einfache Datentypen immer typename genommen.
    Kann das evtl. sogar einen Nachteil haben?



  • CSpille schrieb:

    theta schrieb:

    CSpille schrieb:

    ...

    Das ist nicht korrekt wenn ich mich richtig erinnere.
    class und typename sind in diesem Kontext gleichwertig und austauschbar.

    Simon

    Ehrlich gesagt bin ich jetzt etwas verwirrt...
    Unter welcher Bedingung sind sie denn austauschbar?

    Bisher habe ich für einfache Datentypen immer typename genommen.
    Kann das evtl. sogar einen Nachteil haben?

    nein, in dem kontext ist es vollkommen egal.
    der einzige unterschied, den es gibt ist hier ganz gut beschrieben:
    http://www.informit.com/articles/article.aspx?p=376878

    bb



  • Olli85 schrieb:

    Es besteht folgende (minimierte) Problematik:
    ---------------------------------------------------------------------------
    Die Template-Funktion:
    ...
    template <class T1 , class T2>
    void dieFunktion(T1 wert)
    {
    T2 a = new T2(wert);
    }

    Der ausführende Code (z.B. mit bool)
    ...
    dieFunktion< bool , KlasseX > ( true );

    (Läuft nicht)
    ---------------------------------------------------------------------------
    Normalerweise kann man sich die spitzen Klammern ja sparen, wenn durch die Parameter der Funktion klar ist, um welche Typen es sich handelt.

    Die Fragestellung ist also: Wie ist bitte der Syntax um Template Platzhalter zu verwenden, die nicht durch einen Parameter der Funktion definiert werden?

    Ich verstehe die Frage nicht ganz. Ich vermute, du willst das "bool" nicht mitangeben, da der Compiler sich das selbst über den Parameter true herleiten soll. Dann sortierst Du einfach die Template-Parameter um:

    template <class T2, class T1>  // <--- geändert
    void dieFunktion(T1 wert)
    {
        T2 * a = new T2(wert);
        // ^ 
        // new liefert einen Zeiger
    }
    
    ...
    dieFunktion<KlasseX> ( true );  // <--- geändert
    

    Gruß,
    kk



  • Du kannst ein eigenes Type Promotion basteln, was den Rückgabetyp aus dem Eingabetyp herleitet:

    // Default Template liefert Rückgabetyp T für den Eingabetyp Typ T zurück
    template<typename T>
    struct TypePromotion
    {
       typedef T value_type;
    };
    
    // spezialisiertes Template liefert Rückgabetyp double für den Eingabetyp float zurück
    template<>
    struct TypePromotion<float>
    {
       typedef double value_type;
    };
    
    template<typename T>
    typename TypePromotion<T>::value_type* function( T value )
    {
       return new typename TypePromotion<T>::value_type( value );
    }
    
    int main()
    {
       // Spezialisierung benutzen: float -> double
       double* x = function( 1.0f );
    
       // Default Template benuzten: int -> int
       int*  y = function( 1 );
    
       // Compiler Fehler: keine Typ Promotion von double nach int möglich
       int*  z = function( 1.0 );
    }
    

    Ob das den Aufwand wert ist weiß ich nicht...


Anmelden zum Antworten