std::complex::real: l-value oder nicht?



  • Ist std::complex::real() ein zulässiger l-value oder nicht? (Selbes natürlich auch für imag()).

    Beispiel:

    std::complex<double> c(1.0,1.0);
    
    std::cout << "c = " << c << std::endl;
    
    c.real() = 5.0;
    
    std::cout << "c = " << c << std::endl;
    
    c.imag() = c.real();
    
    std::cout << "c = " << c << std::endl;
    

    compliliert bei mir mit dem g++ 4.2.1 wie erwartet; der g++ 3.3.3 beschwert sich bei den beiden Zuweisen mit einem "error: non-lvalue in assignment". Anscheinend ist mal eine Version von std::complex::real() implementiert, die eine nicht-konstante Referenz zurück gibt, einmal nicht. Andere Compiler habe ich gerade zum testen nicht zur Hand.

    Was sagt denn der Standard dazu? Was sagen andere Compiler?

    [Eben wurde ich auch darauf hingewiesen, dass die Klasse std::complex "eine neuere Erfindung" seien müssen. Wie lange gibts die denn schon im Standard?]



  • Mups schrieb:

    [Eben wurde ich auch darauf hingewiesen, dass die Klasse std::complex "eine neuere Erfindung" seien müssen. Wie lange gibts die denn schon im Standard?]

    Seit 1998...

    real und imag sind folgendermaßen deklariert laut Standard:

    template <class T>
    class complex
    {
    public:
      T real() const;
      T imag() const;
      /* ... */
    };
    


  • pumuckl schrieb:

    Seit 1998...

    Ob ich das meinem Kollegen morgen auf die Nase binden sollte? 🤡

    pumuckl schrieb:

    real und imag sind folgendermaßen deklariert laut Standard:

    template <class T>
    class complex
    {
    public:
      T real() const;
      T imag() const;
      /* ... */
    };
    

    Danke. Weisst du, warum der neuere g++ das offenbar anders macht?



  • Mups schrieb:

    Danke. Weisst du, warum der neuere g++ das offenbar anders macht?

    Die Frage ist warum der alte gcc es anders gemacht hat.

    Der Standard, §3.10,5 schrieb:

    The result of calling a function that does not return a reference is an rvalue.

    Der Standard, §3.10,4 schrieb:

    [Note: Some built-in operators expect lvalue operands [Example: built-in assignment operators all expect their left hand operands to be lvalues. ] [...]]

    Zusammen: c.real() ist ein rvalue, op= erwartet links einen lvalue => das hätte nie funktionieren dürfen.

    Mups schrieb:

    pumuckl schrieb:

    Seit 1998...

    Ob ich das meinem Kollegen morgen auf die Nase binden sollte? 🤡

    Ja... Er scheint sich seit über 10 Jahren nicht besonders intensiv mit dem Standard beschäftigt zu haben. C++0x steht vor der Tür, vielleicht sollte er den alten Standard zumindest ein wenig besser kennen wenn er den Anschluss nicht verlieren will 😉



  • complex.real() bzw. complex.imag() sind r-values. Und was anderes macht nach meiner Einschätzung auch keinen Sinn. Vor zwei Jahren hatten wir zu dem Thema complex.setReal(..) usw. schon mal eine umfangreiche Diskussion.

    Also ganz konkret gefragt: wozu braucht man das - also die Zuweisung z.B. an den real-Wert einer complexen Zahl?

    Gruß
    Werner



  • Werner Salomon schrieb:

    Also ganz konkret gefragt: wozu braucht man das - also die Zuweisung z.B. an den real-Wert einer complexen Zahl?

    Auch wenns etwas umständlich ist, kann mans immernoch ohne größere Probleme hinbiegen:

    c = complex<double>(5.0, c.imag());
    

    Ist etwas umständlicher und mehr zu schreiben, dafür sieht man gleich dass da was ungewöhnliches passiert - aber will die Diskussion von damals jetzt auch nicht unnötig wieder vorkramen 😉



  • pumuckl schrieb:

    Mups schrieb:

    Danke. Weisst du, warum der neuere g++ das offenbar anders macht?

    Die Frage ist warum der alte gcc es anders gemacht hat.

    Der Standard, §3.10,5 schrieb:

    The result of calling a function that does not return a reference is an rvalue.

    Der Standard, §3.10,4 schrieb:

    [Note: Some built-in operators expect lvalue operands [Example: built-in assignment operators all expect their left hand operands to be lvalues. ] [...]]

    Zusammen: c.real() ist ein rvalue, op= erwartet links einen lvalue => das hätte nie funktionieren dürfen.

    Äh... der neuere GCC 4.2.1 hat die Zuweisung c.real() = 5.0; erlaubt, der alte verbietet das. D.h. der neuere GCC verstößt gegen den von dir zitierten Standard, der alte hält ihn ein.

    [ Das "wozu" und workarounds sind mir gerade nicht so wichtig; mich hat vor allem das Unterschiedliche verhalten der beiden Compiler überrascht ]



  • Werner Salomon schrieb:

    Also ganz konkret gefragt: wozu braucht man das - also die Zuweisung z.B. an den real-Wert einer complexen Zahl?

    Mal ganz konkret geantwortet: um den real-Wert zu setzen. 🙂

    Es gibt sicher genug Situationen, wo man den Realwert setzen will und den Imaginärwert so lassen will wie er ist. Zum Beispiel wenn man eine komplexe Zahl komponentenweise berechnet und kein unnötige Variable zum Zwischenspeichern verwenden möchte.


Anmelden zum Antworten