C++ Template-Programmierung: Unterschiedliche Rückgabewerte bei Überladung des "+ Operators"



  • Hallo alle zusammen! 🙂

    Ich habe folgendes Problem und hoffe, dass Ihr mir hier vielleicht weiterhelfen könntet. Es geht um folgendes:

    Ich möchte mir eine Vektoren-Klasse (Vektor im Sinne der Mathematik) schreiben, welche im Moment erst mal einen Punkt im 3-dimensionalen Raum repräsentieren, sowie die Addition zweier 3-dimensionaler Vektoren, sowie einen cast zulassen soll. Der Rest kommt dann im Nachhinein noch dazu^^. Da ich mich aktuell mit der Programmierung mit Templates auseinandersetze, dachte ich, dass dies eine gute Übung hierfür wäre und wollte die Klasse als Template aufbauen. Mein bisheriger Code sieht folgendermaßen aus:

    Hier die Vektor-Klasse in ihrer bisherigen Ausführung:

    Vec3.hpp

    #pragma once
    
    template <typename T>
    class Vec3
    {
    public:
        Vec3()
            : x(0), y(0), z(0)
        {
    
        }
    
        Vec3(T x, T y, T z)
            : x(x), y(y), z(z)
        {
    
        }
    
        template <typename U>
        Vec3 operator+(const Vec3<U>& other)
        {
            Vec3 result;
    
            result.x = this->x + other.x;
            result.y = this->y + other.y;
            result.z = this->z + other.z;
    
            return result;
        }
    
        template <typename U>
        operator Vec3<U>() const
        {
            Vec3<U> result;
    
            result.x = static_cast<U>(this->x);
            result.y = static_cast<U>(this->y);
            result.z = static_cast<U>(this->z);
    
            return result;
        }
    
        T x, y, z;
    };
    

    Hierbei gibt es jetzt folgendes Problem wie in der nachfolgenden Main.cpp zu sehen:

    Main.cpp

    #include "Vec3.hpp"
    
    int main()
    {
        Vec3<int>   vec_1(1, 2, 3);           //Funktioniert.
        Vec3<float> vec_2(1.5f, 2.5f, 3.5f);  //Funktioniert.
    
        Vec3<float> vec_3 = vec_1 + vec_2;    //Falsches Ergebnis...
    
        system("pause");
    
        return 0;
    }
    

    Das Anlegen der Vektoren funktioniert ohne Probleme, aber die Addition liefert ein falsches Ergebnis zurück. Hier erhalte ich folgende Werte für vec_3:

    vec_3.x = 2
    vec_3.y = 4
    vec_3.z = 6

    An sich kann ich das Ergebnis schon nachvollziehen, nur hätte ich gerne folgendes Ergebnis:

    vec_3.x = 2.5
    vec_3.y = 4.5
    vec_3.z = 6.5

    Ich habe auch schon etwas rum probiert, nur funktioniert nichts, da die Addition immer ein Ergebnis des Typs des ersten Summanden zurückgibt, im obigen Beispiel also Vec3<int>.

    Meine Frage wäre nun, kann man dieses Problem mit Templates in den Griff bekommen? Gibt es hier irgend eine Technik, welche ich übersehe? 😕 Wie gesagt bin ich noch ziemlich neu in der Programmierung mit Templates, weshalb ich wohl auch viele wichtige Dinge und Fähigkeiten einfach noch übersehe und nicht kann. Falls Ihr übrigens weitere Vorschläge habt bezüglich meines Codes, bin ich auch dafür jederzeit offen. 🙂

    An dieser Stelle schonmal vielen vielen Dank! 🙂

    Außerdem bin ich ziemlich neu hier im Forum, also falls ich bei meinem Beitrag irgendwas übersehen haben sollte, im falschen Forum bin oder ich ihn besser formatieren sollte usw dann sagt einfach Bescheid 🙂

    Gruß

    Patrick


  • Mod

    Dein operator+ gibt ein Objekt vom Typ des linken Summanden zurück, welcher bei dir den Elementtyp int hat. Dass du damit einen Vektor von Fließkommazahlen initialisierst, ist irrelevant.

    Du solltest den operator+ global machen, und den Elementtyp des Ergebnisses mittels std::common_type bestimmen.



  • Vielen Dank! Jetzt funktioniert alles so wie es soll 🙂



  • Hat common_type in diesem Beispiel einen Vorteil gegenüber decltype(T() + U()) ?


  • Mod

    hustbaer schrieb:

    Hat common_type in diesem Beispiel einen Vorteil gegenüber decltype(T() + U()) ?

    decltype(std::declval<T>() + std::declval<U>()) wäre hier in der Tat besser, da es in Fällen funktionieren kann, in denen common_type eben nicht funktioniert. Insbesondere dann, wenn T und U Typen ohne ein besonderes Verhältnis zueinander sind. Mein Fehler. 🙂


Anmelden zum Antworten