falscher operator aufruf



  • explicit als Schlüsselwort mit rein (Google hilft 😉 )
    Mir ist nur Schleierhaft, wieso das Casten und implizite Umwandeln von int nach float dem direkt passenden operator- und dem Copy-Konstruktor vorgezogen wird. Bei mir ist das nicht so.


  • Mod

    Tachyon schrieb:

    explicit als Schlüsselwort mit rein (Google hilft 😉 )
    Mir ist nur Schleierhaft, wieso das Casten und implizite Umwandeln von int nach float dem direkt passenden operator- und dem Copy-Konstruktor vorgezogen wird. Bei mir ist das nicht so.

    es ist aucht nicht so. Wenn das ein vereinfachtes Beispiel ist, gehe ich davon aus, dass sich beim Vereinfachen ein Fehler eingeschlichen hat.



  • beim vereinfachen ist kein fehler passiert, habe es gerade nochmal durchgeschaut.
    also ich hab mir jetz mal das mit explicit angeschaut, allerdings hab ich jetz ein anderes problem. nämlich:

    T2 var3 = var2 - var1;
    

    das funktioniert jetzt nicht mehr, warum auch nicht?
    weil es gibt ja den copy-constructor über die klasse T, der das eigentlich abwickeln sollte.


  • Mod

    FreakyBKA schrieb:

    beim vereinfachen ist kein fehler passiert, habe es gerade nochmal durchgeschaut.

    Dann sollte es sich aber nicht anders verhalten. Welchen Compiler setzt du denn ein?

    also ich hab mir jetz mal das mit explicit angeschaut, allerdings hab ich jetz ein anderes problem. nämlich:

    T2 var3 = var2 - var1;
    

    das funktioniert jetzt nicht mehr, warum auch nicht?
    weil es gibt ja den copy-constructor über die klasse T, der das eigentlich abwickeln sollte.

    Was heißt funktioniert nicht? Fehlermeldung des Compilers? wenn ja, welche? Im Übrigen sind hier zwei Konstruktoren von T2 beteiligt und die von T eigentlich nur als Teil dieser anderen Konstruktoren.



  • als compiler hab ich den VC++ Express 2005.

    error C2440: 'initializing' : cannot convert from '__w64 int' to 'T2' Constructor for class 'T2' is declared 'explicit'
    

    weil ich jetzt den einen constructor explizit gemacht habe

    explicit T(float x = 0, float y = 0, float z = 0, float v = 0);
    

    also er konvertiert var1 und var2 immernoch in (t*)

    also gedacht war das ja so, das ich die operatoren in T definiere und in T2 mitverwenden kann, weswegen bei var1 - var2 eigentlich was temporäres von Typ T<float, 3> rauskommen sollte und das sollte dann als argument für den anderen constructor bei der Klasse T2 genommen werden.

    das problem ist außerdem noch, das wenn ich statt

    T2 var3 = var1 - var2;
    

    jetzt

    T2 var3(var1 - var2);
    

    schreibe dann nimmt er auch den expliziten constructor von T2 und subtrahiert wieder die zeiger voneinander. 😕



  • Was sagt denn der Compiler, wenn du den operator t* weglässt? (btw, wozu benötigst du den überhaupt?)



  • FreakyBKA schrieb:

    beim vereinfachen ist kein fehler passiert, habe es gerade nochmal durchgeschaut.
    also ich hab mir jetz mal das mit explicit angeschaut, allerdings hab ich jetz ein anderes problem. nämlich:

    T2 var3 = var2 - var1;
    

    das funktioniert jetzt nicht mehr, warum auch nicht?
    weil es gibt ja den copy-constructor über die klasse T, der das eigentlich abwickeln sollte.

    Ich wage mal zu behaupten, daß dann Dein Copy-Konstruktor nicht in Ordnung ist, bzw. nicht existiert. Oder aber Dein operator- gibt einen falschen Typ zurück.

    //falscher Parameter oder nicht vorhanden
    T2(const T<float, 3>& src);
    //bzw.
    //gibt falschen Typ zurück.
    T<t,n> operator - (const T<t,n>& r);
    

    Offensichtlich scheint die Adressdifferenz, die durch das Subtrahieren der Zeiger entsteht, die einzige Variante zu sein, für die ein gültiger Konstruktor existiert (der jetzt aber explicit deklariert wurde).



  • also var1 - var2 sollte ein ergebnis vom typ T<float, 3> liefern, da der Subtraktions-Operator von T aufgerufen werden sollte und für T2 gibt es ja den Konstruktor

    T2(const T<float, 3>& src);
    

    den Cast in (t*) brauch ich in dem programm, weil es bei mir funktionen gibt die diesen typ als argumenttyp haben, aber das ist ja für das problem irrelevant. der cast liefert quasi den zeiger der internen variable

    t data[n];
    

    das sind aber wie gesagt alles nur details.



  • Aber genau dieser Cast scheint das Problem zu sein, weil jetzt außer deinem op- auch der eingebaute op- für Zeiger in Frage kommt für diesen Ausdruck 😉 Wie gesagt, lass mal testweise diesen Operator weg.

    (wenn du an anderer Stelle unbedingt einen t* benötigst, ist vielleicht eine explizite Umwandlungsfunktion 't* data()' geeigneter als ein Umwandlungsoperator)



  • CStoll schrieb:

    Aber genau dieser Cast scheint das Problem zu sein, weil jetzt außer deinem op- auch der eingebaute op- für Zeiger in Frage kommt für diesen Ausdruck 😉 Wie gesagt, lass mal testweise diesen Operator weg.

    Aber der Cast DARF kein Problem sein, denn es ist standardisierte Regel, daß den passenden Typen priorität vor den implizit umzuwandelnden Typen eingeräumt wird. Selbst der eklige und antike MSVC 6.0 hier in der Firma macht das korrekt.
    Ich schätze mal, daß nach wie vor entweder im Rückgabewert von operator- oder im Copy-Konstroktor ein Bock ist, und der Typ eben nicht passt ( vielleicht das kleine t vom Template-Type mit dem großen T der Klasse vertauscht o.ä.). Die Tatsache, daß es plötzlich gar keinen passenden Konstruktor mehr gibt, wenn man den Konvertierungskonstruktor mit den drei Float-Argumenten als explicit deklariert, ist ein weiteres Indiz dafür.



  • das problem ist ich kann den cast-operator nicht einfach weglassen, weil ich dann tausend anderen stellen fehlermeldungen bekomme, die eben genau diesen verwenden.



  • also T2 hat jetzt folgende Konstruktoren

    explicit T2(float x = 0, float y = 0, float z = 0);
    T2(const T<float, 3>& src);
    T2(const T2& src);
    

    dennoch findet er bei der anweisung

    T2 var1, var2;
    //...
    T2 var3 = var1 - var2;
    

    keinen passenden Konstruktor



  • Ehrlich gesagt gehen mir da die Erklärungen aus. Ich habe es mit der von Dir geposteten Templatisierung und Vererbung auf verschiedenen Compilern getestet, und bei mir wird immer der Operator und der Copy-Konstruktor aufgerufen. Bei camper scheint es auch zu laufen.
    Das von Dir beschriebene Verhalten erreiche ich nur, wenn ich den Copy-Konstruktor auskommentiere oder einen anderen Rückgabewert für operator- angebe.



  • FreakyBKA schrieb:

    das problem ist ich kann den cast-operator nicht einfach weglassen, weil ich dann tausend anderen stellen fehlermeldungen bekomme, die eben genau diesen verwenden.

    Beschränk dich bitte erstmal auf das aktuelle Problem - um die "tausend anderen Stellen" kannst du dich später kümmern 😉 (oder auf Deutsch - reduzier' dein Programm/Problem auf das Wesentliche)

    So, wie ich das verstehe, hat der Compiler zwei Möglichkeiten, den Ausdruck "T2 var3 = var1 - var2;" zu deuten:

    1. Verwendung deines op- (vorher Upcast von var1 und var2 in einen T<float,3>&) und des Ctor's 'T2(const T<..>&)'
    2. Verwendung des eingebauten op- für Zeiger (vorher Umwandlung mit deinem operator t*) und des Ctor's 'T2(float,float,float);'

    Nach meinem Verständnis ist Variante 1 "besser", aber offenbar ist dein Compiler anderer Meinung. Also würde ich gerne wissen was herauskommt, wenn du Variante 2 komplett unmöglich machst, indem du die Typumwandlung T/T2 -> float* entfernst. (möglicherweise hast du einen Fehler eingebaut, der Variante 1 unmöglich macht)

    PS: Worin besteht eigentlich der konzeptionelle Unterschied von T2 und T<float,3> - abgesehen von dem Ctor, der drei float-Werte übernehmen kann? Und was spricht dagegen, einen einfachen T<float,3> direkt zu verwenden?



  • CStoll schrieb:

    Nach meinem Verständnis ist Variante 1 "besser", aber offenbar ist dein Compiler anderer Meinung. Also würde ich gerne wissen was herauskommt, wenn du Variante 2 komplett unmöglich machst, indem du die Typumwandlung T/T2 -> float* entfernst. (möglicherweise hast du einen Fehler eingebaut, der Variante 1 unmöglich macht)

    Das hat er im Prinzip schon gezeigt (indem er den 3xfloat-Konstruktor explicit deklariert hat). Den Cast zu entfernen ist nicht notwendig. Danach gabs einen Fehler da kein passender Konstruktor mehr exisierte.
    Meiner Meinung nach kann das nur bedeuten, daß entweder der tatsächlich omplementierte Copy-Kunstruktor nicht dem entspricht, was er hier gepostet hat, oder aber der operator- gibt einen falschen Typen zurück.



  • Was mich stutzig macht, ist aber die Aussage von oben, daß das selbe mit einem global definierten op- funktioniert hat. Also tippe ich mal auf ein Scope-Problem (oder der Klassen-Operator wird nicht gewählt, weil der erste Operand kein T<> ist, sondern ein T2).


  • Mod

    CStoll schrieb:

    So, wie ich das verstehe, hat der Compiler zwei Möglichkeiten, den Ausdruck "T2 var3 = var1 - var2;" zu deuten:

    1. Verwendung deines op- (vorher Upcast von var1 und var2 in einen T<float,3>&) und des Ctor's 'T2(const T<..>&)'
    2. Verwendung des eingebauten op- für Zeiger (vorher Umwandlung mit deinem operator t*) und des Ctor's 'T2(float,float,float);'

    Und so ist es eigentlich nicht. Welcher operator- benutzt wird, hängt ausschließlich von den Parametern ab, nicht davon, ob wir mit dem Funktionsergebnis weiterkommen. Ob also ein passender Konstruktor in T2 existiert, ist dafür völlig irrelevant. Um den eingebauten operator aufrufen zu können, sind hier für beide Parameter selbstdefinierte Konvertierungssequenzen notwendig, während es für den überladenen Operator genügt, je eine derived-to-base-Konvertierung vorzunehmen. Unser Operator ist keine Templatefunktion, also wird diese Konvertierung auch nicht unterdrückt. Dann kann das Ganze nur noch scheitern, wenn diese derived-to-base-Konvertierung wegen Zugriffsbeschränkung oder Mehrdeutigkeit nicht möglich ist - beides offenbar auch nicht der Fall. Ich glaube daher immer noch, dass der Fehler durch die Vereinfachung des Originals verschwunden ist. wie sieht es denn mit

    var1.operator-(var2);
    

    im Original aus?



  • also ich könnte anbieten beide klassen komplett hier drin zu posten, dann wirds aber sehr unübersichtlich, weil viele codezeilen.


  • Mod

    FreakyBKA schrieb:

    also ich könnte anbieten beide klassen komplett hier drin zu posten, dann wirds aber sehr unübersichtlich, weil viele codezeilen.

    Im Zweifel ist das die sicher Variante.



  • ursprünglich die Klasse T

    template <class t, unsigned int n, unsigned int m>
    class cmatrix
    {
    	private:
    
    		t _elements[n * m];
    
    	public:
    
    		cmatrix();
    		cmatrix(const cmatrix<t, n, m>& src);
    
    		void copy(const cmatrix<t, n, m>& src);
    		void load_identity();
    		void load_null();
    		void load_natural();
    		void load_random();
    
    		void set_element(unsigned int i, unsigned int j, const t& e);
    		const t& get_element(unsigned int i, unsigned int j = 0) const;
    
    		void set_col(unsigned int j, const cmatrix<t, n, 1>& col);
    		void set_row(unsigned int i, const cmatrix<t, 1, m>& row);
    		cmatrix<t, n, 1> get_col(unsigned int j) const;
    		cmatrix<t, 1, m> get_row(unsigned int i) const;
    
    		void swap_row(unsigned int i1, unsigned int i2);
    		void swap_col(unsigned int j1, unsigned int j2);
    
    		cmatrix<t, m, n> transpose() const;
    		cmatrix<t, m, n> pseudo_inverse() const;
    
    		void print() const;
    
    //Operatoren
    		void operator = (const cmatrix<t, n, m>& src);
    		cmatrix<t, n, m>& operator ++ ();
    		cmatrix<t, n, m>& operator -- ();
    		t& operator () (unsigned int i, unsigned int j = 0);
    		const t& operator () (unsigned int i, unsigned int j = 0) const;
    		cmatrix<t, n, m> operator () (const cmatrix<unsigned int, n, 1>& p) const;
    		operator const t* () const;
    
    //Vergleichsoperationen
    		bool operator == (const cmatrix<t, n, m>& r) const;
    		bool operator != (const cmatrix<t, n, m>& r) const;
    
    //Negation
    		cmatrix<t, n, m> operator - ();
    
    //Matrix-Matrix-Operationen
    		cmatrix<t, n, m>& operator += (const cmatrix<t, n, m>& r);
    		cmatrix<t, n, m>& operator -= (const cmatrix<t, n, m>& r);
    		cmatrix<t, n, m>& operator *= (const cmatrix<t, m, m>& r);
    		cmatrix<t, n, m> operator + (const cmatrix<t, n, m>& r) const;
    		cmatrix<t, n, m> operator - (const cmatrix<t, n, m>& r) const;
    
    //Matrix-Skalar-Operationen
    		cmatrix<t, n, m>& operator *= (const t& r);
    		cmatrix<t, n, m>& operator /= (const t& r);
    
    		cmatrix<t, n, m> operator * (const t& r) const;
    		cmatrix<t, n, m> operator / (const t& r) const;
    };
    
    //Ausgabeoperation
    template <class t, unsigned int n, unsigned int m>
    ostream& operator << (ostream& os, const cmatrix<t, n, m>& src);
    
    //Matrix-Matrix-Operationen
    template <class t, unsigned int n, unsigned int m, unsigned int p>
    cmatrix<t, n, p> operator * (const cmatrix<t, n, m>& l, const cmatrix<t, m, p>& r);
    
    //Matrix-Skalar-Operationen
    template <class t, unsigned int n, unsigned int m>
    cmatrix<t, n, m> operator * (const t& l, const cmatrix<t, n, m>& r);
    
    //Skalarprodukt
    template <class t, unsigned int n>
    t operator * (const cmatrix<t, n, 1>& l, const cmatrix<t, n, 1>& r);
    

    ursprünglich die Klasse T2

    class cvertex : virtual public cmatrix<float, 4, 1>
    {
    	public:
    
    		cvertex(float x = 0, float y = 0, float z = 0, float v = 0);
    		cvertex(const cmatrix<float, 4, 1>& src);
    		cvertex(const cvertex& src);
    
    		void set(float x = 0, float y = 0, float z = 0, float v = 0);
    		void set_point();
    		void set_vector();
    		void set_affine();
    		void set_positive();
    
    		float x() const;
    		float y() const;
    		float z() const;
    		float abs2() const;
    		float abs() const;
    		void normalize();
    
    		void draw(float red = 1, float green = 1, float blue = 1, float alpha = 1) const;
    		void set_dot() const;
    
    		void print() const;
    
    		void operator = (const cmatrix<float, 4, 1>& src);
    		void operator = (const cvertex& src);
    		cvertex operator - () const;
    		cvertex& operator ^= (const cvertex& r);
    };
    
    ostream& operator << (ostream& os, const cvertex& src);
    cvertex operator ^ (const cvertex& l, const cvertex& r);
    
    float volume(const cvertex& a, const cvertex& b, const cvertex& c);
    float abs(const cvertex& vertex);
    float abs2(const cvertex& vertex);
    

    bitte nicht schlagen 😃


Anmelden zum Antworten