Operatoren und Implizite Konversion



  • Hallo

    Ich habe das Problem, dass bei unten stehender Klasse die implizite Konversion bei den externen operatoren nicht funktioniert. Eigentlich wollte ich erreichen, dass man einen Vector direkt mit einer Zahl z.B. multiplizieren kann, ohne dass es eine Rolle spielt, auf welcher seite die Zahl steht. Leider weigert sich VC++ 2005 die Zahl in einen Vector umzuwandeln. Weiss jemand wieso?

    Gruss

    Stefan

    #ifndef VECTOR_H
    #define VECTOR_H
    
    template<typename T>
    struct Vector
    {
    	T x, y, z;
    
    	Vector(T val = 0)
    	{
    		this->x = val;
    		this->y = val;
    		this->z = val;
    	}
    
    	Vector(T x, T y, T z)
    	{
    		this->x = x;
    		this->y = y;
    		this->z = z;
    	}
    
    	Vector& operator += (const Vector &vec)
    	{
    		this->x += vec.x;
    		this->y += vec.y;
    		this->z += vec.z;
    		return *this;
    	}
    
    	Vector& operator -= (const Vector &vec)
    	{
    		this->x -= vec.x;
    		this->y -= vec.y;
    		this->z -= vec.z;
    		return *this;
    	}
    
    	Vector& operator *= (const Vector &vec)
    	{
    		this->x *= vec.x;
    		this->y *= vec.y;
    		this->z *= vec.z;
    		return *this;
    	}
    
    	Vector& operator /= (const Vector &vec)
    	{
    		this->x /= vec.x;
    		this->y /= vec.y;
    		this->z /= vec.z;
    		return *this;
    	}
    };
    
    template<typename T>
    Vector<T> operator + (const Vector<T> &v1, const Vector<T> &v2)
    {
    	return Vector<T>(v1) += v2;
    }
    
    template<typename T>
    Vector<T> operator - (const Vector<T> &v1, const Vector<T> &v2)
    {
    	return Vector<T>(v1) -= v2;
    }
    
    template<typename T>
    Vector<T> operator * (const Vector<T> &v1, const Vector<T> &v2)
    {
    	return Vector<T>(v1) *= v2;
    }
    
    template<typename T>
    Vector<T> operator / (const Vector<T> &v1, const Vector<T> &v2)
    {
    	return Vector<T>(v1) /= v2;
    }
    
    #endif
    


  • Hi,
    hmmmm lange Geschichte, ist wegen den Templates so. Hatten wir in letzter Zeit schon nen paar Mal hier. Ich suche mal nach nem Link, damit ich nichts schreiben muss 🙂



  • Siehe da : http://c-plusplus.net/forum/viewtopic-var-t-is-161613-and-highlight-is-.html Ich hatte auch mal diese Frage gestellt 🙂



  • Und hier auch noch nen Link, wo du auch direkt siehst wie es bei dir aussehen musst, damits funktioniert, wenn du noch eine zusätzliche Erklärung brauchst, dann kriegste wieder ein paar Links 🙂


  • Mod

    Für Parameter, die zur Deduktion von Templateparametern genutzt werden, sind die meisten impliziten Konvertierungen (und selbstdefinierte sowieso) unterdrückt. Etwas Anderes würde zu viele Mehrdeutigkeiten produzieren; aus dem gleichen Grunde kann eine implizite Konvertierungssequenz immer nur höchtens einen selbstdefinierten Operator/Konstruktor enthalten. Wie so oft gibt es mehr als eine Möglichkeit, das Problem zu umgehen:
    1. an Stelle von Templates verwenden wir normale Funktionen, und überladen für jeden Templateparameter:

    template<typename T>
    struct Vector
    {
    ...
    friend Vector operator + (const Vector &v1, const Vector &v2)
    {
        return Vector(v1) += v2;
    }
    ...
    };
    

    Im Allgemeinen sollte man mit diesem Verfahren vorsichtig sein, weil das komplette Set überladener Funktionen davon abhängt, welche Templates instantiiert wurden. In diesem Falle sehe ich da allerdings keine Probleme.

    2. wir deduzieren verschiedene Templateparameter und verlassen uns darauf, dass für fehlerhafte Paramater das Instantiieren fehlschlägt:

    template<typename T, typename U>
    Vector<T> operator + (const U &v1, const Vector<T> &v2)
    {
        return Vector<T>(v2) += v1;
    }
    
    template<typename T, typename U>
    Vector<T> operator + (const Vector<T> &v1, const U &v2)
    {
        return Vector<T>(v1) += v2;
    }
    
    template<typename T, typename U>
    Vector<T> operator + (const Vector<U> &v1, const Vector<T> &v2)
    {
        return Vector<T>(v1) += v2;
    }
    

    3. etwas verfeinert könnten wir auch einen Parametr zwar vom Templateparameter abhängig machen, aber so, dass ein nicht deduzierbarer Kontext ensteht:

    template<typename T> struct Identity { typedef T type; }; // die einfachsten Konstrukte sind oft sehr nützlich
    
    template<typename T>
    Vector<T> operator + (const typename Identity<Vector<T> >::type &v1, const Vector<T> &v2) // Linker Parameter ist nicht deduzierbar
    {
        return Vector<T>(v2) += v1;
    }
    
    template<typename T, typename U>
    Vector<T> operator + (const Vector<T> &v1, const typename Identity<Vector<T> >::type &v2)
    {
        return Vector<T>(v1) += v2;
    }
    
    template<typename T>
    Vector<T> operator + (const Vector<T> &v1, const Vector<T> &v2)
    {
        return Vector<T>(v1) += v2;
    }
    

    das sind die Möglichkeiten, die mir unmittelbar einfallen - sicher gibt es noch mehr



  • Danke euch beiden! 🙂



  • Uuups:

    KasF schrieb:

    Und hier auch noch nen Link, wo du auch direkt siehst wie es bei dir aussehen musst, damits funktioniert, wenn du noch eine zusätzliche Erklärung brauchst, dann kriegste wieder ein paar Links 🙂

    http://www.parashift.com/c++-faq-lite/templates.html#faq-35.16



  • hi,
    KasF, Ubr und hustbaer haben mir vor kurzem bei einem ähnlichen Problem sehr geholfen. Vielleicht nützen dir einige Details meiner Matrixklasse (an der ich gerade wieder rumprogrammiere), denn die Operatorüberladung funktioniert nun.

    http://www.c-plusplus.net/forum/viewtopic-var-t-is-182721.html

    vg tesu


Anmelden zum Antworten