wieso funktioniert dieses template nicht?



  • template<typename T,typename U=T>
    struct Pair
    {
     T first;
     U second;
    
     Pair(const T& a,const U& b):first(a),second(b){}
     Pair(const Pair& Obj):first(Obj.first),second(Obj.second){}
     Pair& operator=(const Pair&);
    
    };
    
    template<typename T,typename U>
    Pair<T,U>&::Pair<T,U> operator=(const Pair<T,U>& Obj)
    {
     first = Obj.first;
     second = Obj.second;
    }
    

    Fehler:

    [C++ Fehler] Unit1.cpp(29): E2428 Templates müssen Klassen oder Funktionen sein
    [C++ Fehler] Unit1.cpp(29): E2238 Bezeichner 'Pair<T,U>' mehrfach deklariert
    [C++ Fehler] Unit1.cpp(18): E2344 'Pair<T,U>' bereits deklariert
    [C++ Fehler] Unit1.cpp(29): E2356 Redeklaration von 'Pair<T,U>' mit anderem Typ
    [C++ Fehler] Unit1.cpp(18): E2344 'Pair<T,U>' bereits deklariert
    [C++ Fehler] Unit1.cpp(29): E2141 Fehler in der Deklarationssyntax
    


  • Hi!

    Wetten der Fehler liegt hier:

    Pair<T,U>&::Pair<T,U> operator=(const Pair<T,U>& Obj)
    

    Eher so:

    Pair<T,U>& Pair<T,U>::operator=(const Pair<T,U>& Obj)
    

    Du solltest außerdem *this zurückgeben... Weil du als Rückgabewert ja Pair<T,U>& definiert hast.

    grüße



  • jap, und eine Prüfung auf Selbstzuweisung muss auch rein:

    template<typename T,typename U>
    Pair<T,U>& Pair<T,U>::operator=(const Pair<T,U>& Obj) {
      if (this == &Obj)
        return *this;
    
      first = Obj.first;
      second = Obj.second;
      return *this;
    };
    

    MfG

    GPC



  • "[C++ Fehler] Unit1.cpp(29): E2428 Templates müssen Klassen oder Funktionen sein"

    das würde ich auch noch beachten, wenn der compiler schon darauf hinweist 😉

    mfg



  • GPC schrieb:

    jap, und eine Prüfung auf Selbstzuweisung muss auch rein:
    [...]

    wozu sollte man sowas machen müssen?



  • wozu? schrieb:

    GPC schrieb:

    jap, und eine Prüfung auf Selbstzuweisung muss auch rein:
    [...]

    wozu sollte man sowas machen müssen?

    Weil eine Selbstzuweisung unsinnig ist, wieso sollte es sinnvoll sein, einem Objekt die Werte, die es ohnehin schon hat, nochmal zuzuweisen? Kostet nur. Bei der Pair-Klasse kann das schon Auswirkungen haben, denn der erste Template-Parameter könnte eine große Klasse mit einigen Membern sein, die dann auch noch unnötig kopiert werden.

    Klar, du würdest nicht

    struct Foo {
      //...
    };
    
    Foo x;
    x = x;
    

    schreiben, aber weißt du, was hinter jeder Referenz, jedem Pointer oder SmartPointer steckt? Ich nicht.

    MfG

    GPC



  • naja, hier viell nich dringend notwendig!
    aber wenn du mit dynamischen objekten arbeitest ist es besser!

    denn im zuweisungsoperator löscht du das alte objekt, damit das neue zugeordnet werden kann!

    bei einer selbstzuweisung löscht du etwas, und willst dann deinem neuen objekt das gelöschte zuordnen, geht ja nicht!



  • GPC schrieb:

    jap, und eine Prüfung auf Selbstzuweisung muss auch rein

    IdR nicht.

    GPC schrieb:

    Weil eine Selbstzuweisung unsinnig ist, wieso sollte es sinnvoll sein, einem Objekt die Werte, die es ohnehin schon hat, nochmal zuzuweisen? Kostet nur.

    Was unsinnig ist, ist die Abfrage auf Selbstzuweisung. Selbstzuweisung tritt so gut wie nie auf, daher zu vernachlässigen. Wozu sollte man also jeder Zuweisung den Overhead der Abfrage aufzwingen, wenn das praktisch nutzlos ist? Eine Abfrage macht nur dann Sinn und sollte auch nur dann verwendet werden, wenn sich sonst logische Fehler ergeben. Und selbst bei dynamischen Objekten ist die Abfrgae auf Selbstzuweisung nicht zwangsläufig notwendig.

    ser1al(ausgeloggt) schrieb:

    denn im zuweisungsoperator löscht du das alte objekt, damit das neue zugeordnet werden kann!

    bei einer selbstzuweisung löscht du etwas, und willst dann deinem neuen objekt das gelöschte zuordnen, geht ja nicht!

    Deshalb macht man das auch nicht so. ➡ neuen Speicher anfordern, Daten kopieren, alten Speicher freigeben ... dann gibt's auch keine Probleme

    @sadasd
    Lass den copy ctor und copy op einfach weg, das kann dein Compiler schon selber. Sowas ist nur in bestimmten Situationen notwendig, zB wenn deine Klasse Member hat, welchen dynamischer Speicher zugewiesen wurde, wo sonst Speicherlöcher entstehen würden. In diesem Zusammenhang solltest du dir auch mal Law of the big three anschauen.



  • groovemaster schrieb:

    GPC schrieb:

    Weil eine Selbstzuweisung unsinnig ist, wieso sollte es sinnvoll sein, einem Objekt die Werte, die es ohnehin schon hat, nochmal zuzuweisen? Kostet nur.

    Was unsinnig ist, ist die Abfrage auf Selbstzuweisung. Selbstzuweisung tritt so gut wie nie auf, daher zu vernachlässigen.

    Kannst du das irgendwie belegen, oder ist das jetzt halt so aus deiner Erfahrung?

    Wozu sollte man also jeder Zuweisung den Overhead der Abfrage aufzwingen, wenn das praktisch nutzlos ist? Eine Abfrage macht nur dann Sinn und sollte auch nur dann verwendet werden, wenn sich sonst logische Fehler ergeben. Und selbst bei dynamischen Objekten ist die Abfrgae auf Selbstzuweisung nicht zwangsläufig notwendig.

    Gut gut, aber ist es nicht schwachsinnig, ein Objekt sich selbst zuzuweisen (nehmen wir mal an, es passiert doch), das kostet doch ebenfalls Performance. Oder spielst du darauf an, dass dieses eine mal weniger teuer ist, als n - mal die Abfrage?

    EDIT: Ja, genau darauf wolltest du wohl hinaus, hab grad mal bei Marshall Cline reingeschaut, er hat's ganz gut drinstehen. Tja, die Runde geht an dich. Wieder was gelernt...

    MfG

    GPC


Anmelden zum Antworten