Schwierigkeiten mit templates



  • Bevor ich eine genauere Erklärung gebe, möchte ich dir eine Frage stellen. Vielleicht hilft dir das, zu verstehen, wie mein max funktioniert.

    int a = 2, b = 3;
    double c = 4., d = 1.;
    
    auto e = a > c ? a : c;
    auto f = b > d ? b : d;
    

    Von welchem Typ sind e und f? 😉



  • double

    weil das muss zur compilezeit ausgewertet werden, aber der ausdruck selbst wird nicht unbedingt (kann duch optimierungen oder sowas schon) ausgewertet. sprich der compiler sucht nach einem kompromiss, was für beides geht. und da ein int implizit nach double castable ist ---> double



  • War eigentlich an Sone gerichtet, hätte ich dazuschreiben sollen. Aber ja, das ist korrekt.



  • ok, weil ich wusste es auch nicht bestimmtheit und wollte es mal testen 😉

    kann man in dem forum so ne art spoiler funktion nutzen?


  • Mod

    Skym0sh0 schrieb:

    kann man in dem forum so ne art spoiler funktion nutzen?

    Nein, das wäre in einem Programmierfachforum keine häufig genutzte Funktion. Du kannst so etwas emulieren, indem du einen Link zu Pastebin, ideone oder ähnlichem benutzt, dem ein Leser dann optional folgen kann oder nicht.



  • Skym0sh0 schrieb:

    kann man in dem forum so ne art spoiler funktion nutzen?

    rot13 verschlüsseln 😉
    wir sind hier unter programmierern



  • Ich hab es schon durch Shades Beitrag verstanden. Ich wusste auch schon, dass die Ausdrücke nicht ausgewertet werden :), denn auch ich verwende decltype() oft. Nur, dachte ich, ist es so, dass hier entschieden wird, welcher Typ zurückgegeben wird, anhand der Werte der Variablen 😃

    Wenn ich es jetzt richtig verstanden habe, dann kannst du aber auch gleich

    template <typename T1, typename T2>
    typename std::common_type<T1, T2>::type max(T1 t1, T2 t2)
    {
        return t1 > t2 ? t1 : t2;
    }
    

    schreiben, oder?



  • Sone schrieb:

    std::common_type<T1, T2>::type

    Ja.
    Sofern common_type das korrekte macht. Ich denke ja, habe es aber noch nie verwendet.
    Das coole and decltype ist, dass es direkt den Code widerspiegelt. So ist zB
    declytpe(char(1)*char(1)) == int
    während common_type<char, char>::type == char wäre.

    In diesem Fall wäre common_type OK, aber das sollte man dennoch im Hinterkopf behalten.


  • Mod

    Shade Of Mine schrieb:

    Sofern common_type das korrekte macht. Ich denke ja, habe es aber noch nie verwendet.

    common_type (sofern nicht durch den Nutzer spezialisiert) ist über decltype(true?declval<T>():declval<U>()) definiert (20.9.7.6/3)

    Eine etwas bessere Variante dürfte

    template <typename T1, typename T2>
    typename std::common_type<T1, T2>::type max(T1&& t1, T2&& t2)
    {
        return t1 < t2 ? std::forward<T2>( t2 ): std::forward<T1>( t1 );
    }
    

    sein. Damit wird auch mit kompatiblen lvalues sinnvoll umgegangen (und bei Gleichheit hat der linke Parameter Vorrang, was bei Verkettung das Naheliegendere sein dürfte).



  • t1 < t2 ? std::forward<T1>( t2 ): std::forward<T2>( t1 );

    das soll
    t1 < t2 ? std::forward<T2>( t2 ): std::forward<T1>( t1 );
    heissen nehme ich an, oder?


  • Mod

    Shade Of Mine schrieb:

    t1 < t2 ? std::forward<T1>( t2 ): std::forward<T2>( t1 );

    das soll
    t1 < t2 ? std::forward<T2>( t2 ): std::forward<T1>( t1 );
    heissen nehme ich an, oder?

    ja.



  • Shade Of Mine schrieb:

    t1 < t2 ? std::forward<T1>( t2 ): std::forward<T2>( t1 );

    das soll
    t1 < t2 ? std::forward<T2>( t2 ): std::forward<T1>( t1 );
    heissen nehme ich an, oder?

    Wird das nicht eh automatisch deduziert?



  • Sone schrieb:

    Shade Of Mine schrieb:

    t1 < t2 ? std::forward<T1>( t2 ): std::forward<T2>( t1 );

    das soll
    t1 < t2 ? std::forward<T2>( t2 ): std::forward<T1>( t1 );
    heissen nehme ich an, oder?

    Wird das nicht eh automatisch deduziert?

    Nein, du gibst ja explizit den Typ an.
    Und forward<T1>(t2) wuerde t2 ja in T1 konvertieren. Was uU schlecht waere, wenn T1 zB int und T2 double waere.



  • Shade Of Mine schrieb:

    Sone schrieb:

    Shade Of Mine schrieb:

    t1 < t2 ? std::forward<T1>( t2 ): std::forward<T2>( t1 );

    das soll
    t1 < t2 ? std::forward<T2>( t2 ): std::forward<T1>( t1 );
    heissen nehme ich an, oder?

    Wird das nicht eh automatisch deduziert?

    Nein, du gibst ja explizit den Typ an.

    Das ist es ja, ich dachte man kann die explizite Angabe wegfallen lassen.

    t1 < t2 ? std::forward( t2 ): std::forward( t1 );
    


  • Nein. forward will wissen, ob der Typ vor Reference Collapsing eine Lvalue-Referenz war oder nicht, weil es danach nicht mehr eindeutig ist.


Anmelden zum Antworten