Kurze Frage zu Beispiel aus C++ Templates: The Complete Guide



  • Hallo allerseits,
    ich fange gerade an das Buch "C++ Templates: The Complete Guide" zu lesen. Im Kapitel zur Überladung von Funktionstemplates gibt es ein Beispiel, bei dem ich nicht weiß, ob ich das richtig verstanden habe:

    #include <iostream> 
    #include <cstring> 
    #include <string> 
    
    // maximum of two values of any type (call-by-reference) 
    template <typename T> 
    inline T const& max (T const& a, T const& b) 
    { 
        return a < b ? b : a; 
    } 
    
    // maximum of two C-strings (call-by-value) 
    inline char const* max (char const* a, char const* b) 
    { 
        return std::strcmp(a,b) < 0 ? b : a; 
    } 
    
    // maximum of three values of any type (call-by-reference) 
    template <typename T> 
    inline T const& max (T const& a, T const& b, T const& c) 
    { 
        return max (max(a,b), c); // error, if max(a,b) uses call-by-value 
    } 
    
    int main () 
    { 
        ::max(7, 42, 68); // OK 
    
        const char* s1 = "frederic"; 
        const char* s2 = "anica"; 
        const char* s3 = "lucas"; 
    
       ::max(s1, s2, s3); // ERROR 
    }
    

    Kompiliert mit folgender Warnung:

    returning address of local variable or temporary
    

    Kurz zur Benennung: das max mit den 2 Parametern nenne ich mal max2, das mit den 3 Parametern max3.
    So wie ich das vertanden habe, wird erst max3 initialisiert. Das "T" ist dabei "char*". Da es eine Nicht-Template Funktion gibt, die "const char*" erwartet, wird diese Funktion für max2 Variante gewählt und die templateversion von max2 garnicht erst initialisiert. Beim Aufruf von max3 werden die Zeiger als Referenz übergeben. max2 erwartet aber eine Kopie, also werden die Zeiger, die als Refernz an max3 weitergegeben wurden, in die lokalen Variablen von max2 kopiert. Der Rückgabewert von max2 ist eine Kopie der lokalen Variable von max2. max3 möchte aber eine Referenz darauf zurückgeben, wodurch eine Referenz auf eine lokale Variable entstehen würde.
    Ist das so richtig, oder liege ich völlig daneben? 😃



  • Der Rückgabewert von max2 ist eine Kopie der lokalen Variable von max2. max3 möchte aber eine Referenz darauf zurückgeben, wodurch eine Referenz auf eine lokale Variable entstehen würde.

    Jup, genau.

    Beim Aufruf von max3 werden die Zeiger als Referenz übergeben.

    Jo.

    Das "T" ist dabei "char*".

    Nope, das T ist char const* .
    Wie kommst du darauf?

    Zu den Begrifflichkeiten: Du meinst instantiiert.



  • Sone schrieb:

    Das "T" ist dabei "char*".

    Nope, das T ist char const* .
    Wie kommst du darauf?

    Zu den Begrifflichkeiten: Du meinst instantiiert.

    Da, du hast bei beiden Punkten vollkommen recht. Wenn das sonst so stimmt, dann bin ich ja ganz zufrieden :>



  • TMPAnfänger schrieb:

    Sone schrieb:

    Das "T" ist dabei "char*".

    Nope, das T ist char const* .
    Wie kommst du darauf?

    Zu den Begrifflichkeiten: Du meinst instantiiert.

    Da, du hast bei beiden Punkten vollkommen recht. Wenn das sonst so stimmt, dann bin ich ja ganz zufrieden :>

    Wie ich mal in meiner Signatur stehen hatte: C++-Templates - Metaquark vom feinsten.
    Ist halt alles recht kompliziert.



  • Eine Sache fällt mir noch auf:

    Da es eine Nicht-Template Funktion gibt, die "const char*" erwartet, wird diese Funktion für max2 Variante gewählt und die templateversion von max2 garnicht erst initialisiert.

    Das wurde in deinem Beispiel bereits instantiiert. 😉

    Übrigens ist es eine merkwürdige Angewohnheit, den globalen Scope-Operator zu verwenden.



  • Sone schrieb:

    Übrigens ist es eine merkwürdige Angewohnheit, den globalen Scope-Operator zu verwenden.

    Habe ich mir auch gedacht. Im Buch wird es gemacht, damit nicht std::max verwendet wird. Falls ::max mit Typen aufgerufen wird, die im std Namespace stehen, ann sucht er nach max ja auch im std-Namespace.



  • TMPAnfänger schrieb:

    Sone schrieb:

    Übrigens ist es eine merkwürdige Angewohnheit, den globalen Scope-Operator zu verwenden.

    Habe ich mir auch gedacht. Im Buch wird es gemacht, damit nicht std::max verwendet wird. Falls ::max mit Typen aufgerufen wird, die im std Namespace stehen, ann sucht er nach max ja auch im std-Namespace.

    std::max kann gar nicht gefunden werden, weil es nicht bekannt ist. 😉



  • Sone schrieb:

    TMPAnfänger schrieb:

    Sone schrieb:

    Übrigens ist es eine merkwürdige Angewohnheit, den globalen Scope-Operator zu verwenden.

    Habe ich mir auch gedacht. Im Buch wird es gemacht, damit nicht std::max verwendet wird. Falls ::max mit Typen aufgerufen wird, die im std Namespace stehen, ann sucht er nach max ja auch im std-Namespace.

    std::max kann gar nicht gefunden werden, weil es nicht bekannt ist. 😉

    Welche Antwort hingegen hätte am meisten geholfen?



  • volkard schrieb:

    Welche Antwort hingegen hätte am meisten geholfen?

    Ups, ich hab die Antwort nicht komplett durchgelesen.

    Neh, in dem Fall wäre wohl ein anderer Name adäquat. Sowas wie myMax. Dann muss man sich um so einen Quatsch keine Sorgen mehr machen.


Anmelden zum Antworten