Cast operator wird nicht verwendet



  • Hi,

    das folgende Beispiel wird von Visual Studion 2010 und von Borland C++ Builder überset:

    #include <iostream>
    
    struct ClassB;
    
    struct ClassA
    {
    	int	m_x, m_y;
    
    	ClassA( int x, int y=1 ) : m_x(x), m_y(y)
    	{
    	}
    
    	operator double() const
    	{
    		return m_x * m_y;
    	}
    };
    
    struct ClassB
    {
    	int		m_x;
    	ClassA	m_a;
    
    	ClassB( int x, int y, int z ) : m_x(x), m_a(y, z)
    	{
    	}
    
    	operator double() const
    	{
    		return m_x * double(m_a);
    	}
    	operator ClassA() const
    	{
    		return m_a;
    	}
    };
    
    int main()
    {
    	ClassB	b( 4, 2, 3 );
    	ClassA	a( b );
    
    	std::cout << double(b) << ' ' << double(a) << std::endl;
    }
    

    gcc bringt aber folgenden Fehler:
    `badconvert.cpp: In function ‘int main()’:

    badconvert.cpp:41: error: call of overloaded ‘ClassA(ClassB&)’ is ambiguous

    badconvert.cpp:9: note: candidates are: ClassA::ClassA(int, int)

    badconvert.cpp:6: note: ClassA::ClassA(const ClassA&)`

    Wer hat recht und warum?

    VG Martin


  • Mod

    mgaeckler schrieb:

    Wer hat recht und warum?

    gcc vs Visual C++ || Borland C++ ?
    Die gcc-Version hast du zwar nicht angegeben, aber hier besteht immer die große Wahrscheinlichkeit, dass gcc recht hat.

    Implizite Konvertierungssequenzen, die nutzerdefinierte Konvertierungsfunktionen (also Konstruktoren oder Konvertierungsoperatoren) enthalten, können nur dann unterschieden werden, wenn sie die gleiche Konvertierungsfunktion verwenden; andernfalls sind sie in jedem Fall gleichrangig.

    Im Beispiel gibt es 3 Möglichkeiten:
    (1) B::operator double() -> int -> Aufruf des (int,int=1) Konstruktors
    (2) B::operator A() -> Aufruf des (const A&) Copy-ctors
    (3) B::operator A() -> Aufruf des (A&&) Move-ctors

    (3) ist besser als (2) (gleiche Konvertierungsfunktion, und die Ranking-Regeln für Referenzinitialisierung greifen) , aber keine Variante ist gleichzeitig besser als die beiden Anderen.



  • Hi,

    erstmal danke für Deine Antwort.

    camper schrieb:

    mgaeckler schrieb:

    Wer hat recht und warum?

    gcc vs Visual C++ || Borland C++ ?
    Die gcc-Version hast du zwar nicht angegeben, aber hier besteht immer die große Wahrscheinlichkeit, dass gcc recht hat.

    In diesem Fall war es 4.3. Da aber auch neuere den gleichen Fehler meldeten, habe ich es versäumt, die Version anzugeben. Im übrigen traue ich hier gcc auch eher die Standardkonformität zu als den beiden anderen. 😃

    camper schrieb:

    Implizite Konvertierungssequenzen, die nutzerdefinierte Konvertierungsfunktionen (also Konstruktoren oder Konvertierungsoperatoren) enthalten, können nur dann unterschieden werden, wenn sie die gleiche Konvertierungsfunktion verwenden; andernfalls sind sie in jedem Fall gleichrangig.

    Im Beispiel gibt es 3 Möglichkeiten:
    (1) B::operator double() -> int -> Aufruf des (int,int=1) Konstruktors
    (2) B::operator A() -> Aufruf des (const A&) Copy-ctors
    (3) B::operator A() -> Aufruf des (A&&) Move-ctors

    (3) ist besser als (2) (gleiche Konvertierungsfunktion, und die Ranking-Regeln für Referenzinitialisierung greifen) , aber keine Variante ist gleichzeitig besser als die beiden Anderen.

    Ich hätte jetzt gedacht, daß (1) unzulässig ist, weil noch ein weiterer, impliziter Konvertierungsschritt notwendig ist, der noch dazu mit Datenverlust verbunden ist.

    Ich habe jedenfalls als Konsequenz die Regel eingeführt, lieber einen Konstruktor als einen cast operator zu definieren, wenn ich Quell- und Zieltyp definiert habe.

    VG Martin


Anmelden zum Antworten