valarray (slice_array) problem oder gcc problem, oder noch nicht korrigierter stroustrup fehler?



  • Hallo, ich bin mir nicht sicher, ob es ein Standard C++ Problem ist, oder ein gcc spezifisches. Folgendes Minimalbeispiel:

    #include <valarray>
    using namespace std;
    
    void foo (valarray<double> &vd) {
    	slice_array<double> &sl_gerade = vd[slice(0, vd.size()/2+vd.size()%2,2)];
            //benutzt wie im stroustrup vorgestellt
    	sl_gerade = 10;
    }
    
    int main () {
    	double x [] = { 0., 1., 2., 3. };
    	valarray<double> v(x,4);
    	foo(v);
    }
    

    funktioniert nicht: g++ 3.3, 3.2 und 2.96 (in der reihenfolge) melden:

    [david@DAVID Tests]$ g++ main.cpp -o mai
    main.cpp: In function `void foo(std::valarray<double>&)':
    main.cpp:10: error: could not convert `
       std::valarray<_Tp>::operator[](std::slice) [with _Tp = double](slice(0,
       (((+vd)->std::valarray<_Tp>::size() const [with _Tp = double]() / 2) +
       ((+vd)->std::valarray<_Tp>::size() const [with _Tp = double]() % 2)), 2))'
       to `std::slice_array<double>&'
    
    [david@DAVID Tests]$ /usr/bin/g++ main.cpp -o mai
    main.cpp: In function `void foo(std::valarray<double>&)':
    main.cpp:10: initialization of non-const reference type `class
       std::slice_array<double>&' from rvalue of type `std::slice_array<double>'
    
    [david@DAVID Tests]$ /usr/bin/g++296 main.cpp -o mai
    main.cpp: In function `void foo (valarray<double> &)':
    main.cpp:10: initialization of non-const reference type `class
    slice_array<double> &'
    main.cpp:10: from rvalue of type `slice_array<double>'
    

    was mir noch einleuchtend erscheint, sind die ergebnisse von 3.2 und 2.96

    folgendes funktioniert jedoch:

    int main () {
    	double x [] = { 0., 1., 2., 3. };
    	valarray<double> vd(x,4);
            vd[slice(0, vd.size()/2+vd.size()%2,2)] = 0;
    
            valarray<double> v_split = vd[slice(0, vd.size()/2+vd.size()%2,2)];
    }
    

    wie benutze ich slice_array korrekt?
    benutze ich es korrekt, und g++ kann nicht? dann verschiebt mich bitte ins entsprechende forum (andere compiler)

    edit: den header hab ich überprüft, ist standardkonform. übrigens: mit

    void *tmp = static_cast<void*>(&vd[slice(1,2,3)]);
    slice_array<double> &sl = *static_cast<slice_array<double>*>(tmp);
    

    klappt's schon. seltsam, da kommt nur die warnung: warning: using temporary.



  • vd[slice(0, vd.size()/2+vd.size()%2,2)];

    Liefert ein slice_array<double> by value, was natürlich kein lvalue ist. Demzufolge kannst du das Ergbnis nicht zur Initialisierung einer Referenz verwenden.
    Die Ergebnisse von 3.2 und 2.96 sind also genau richtig.

    folgendes funktioniert jedoch:

    vd[slice(0, vd.size()/2+vd.size()%2,2)] = 0;
    

    Sicher. Das ruft den operator= auf dem temporären slice_array-Objekt auf.

    übrigens: mit

    void *tmp = static_cast<void*>(&vd[slice(1,2,3)]); 
    slice_array<double> &sl = *static_cast<slice_array<double>*>(tmp);
    

    klappt's schon. seltsam, da kommt nur die warnung: warning: using temporary

    Das dürfte nicht funktionieren. Das Argument für den unären Operator & muss ein lvalue sein.



  • ja, genau wie ich es mir dachte. aber wieso verwendet stroustrup es in seinem Buch genau so mit einer referenz? du hast sicher das buch zur hand. seite 720 (in der deutschen ausgabe der special edition)
    dort haben wir (1 zu 1 abgeschrieben):

    void f (valarray<double>& vd)
    {
        slice_array<double>& v_gerade = vd[slice(0,vd.size()/2+vd.size()%2,2)];
        slice_array<double>& v_ungerade = vd[slice(1,vd.size()/2,2)];
    
        v_gerade *= v_ungerade;
        v_ungerade = 0;
    }
    

    über google finde ich nur noch jemanden, der dasselbe problem hat. und die errate auf bjarnes homepage zu durchforsten dauert zu lange, schließlich weiß ich ja nicht, welche seite es in der englischen version ist...
    und das durchforsten der seite bringt nichts. einmal korrigiert er die funktion, und lässt die referenzen stehen.

    oder überseh ich da was? ich wunder mich jetzt schon den ganzen tag über dieses beispiel...



  • in der englischen (3. ed bzw. special ed.) ist das Beispiel auf Seite 671. Unterschied zur deutschen Version: der Parameter heißt d statt vd, v_gerade/ungerade heißen v_even/odd.



  • Hallo,
    scheint ein Fehler zu sein:
    Gefunden habe ich:
    das

    und das



  • wie kann die Funktion

    slice_array<T> valarray<T>::operator[](slice)
    

    überhaupt funktionieren, wenn slice_array 1) einen privaten copy-ctor hat und dieser 2) lt. Standard nicht implementiert sein muss?



  • da wird ja nichts kopiert, oder was meinst du?
    auf jedenfall danke für die auskünfte bis jetzt. dann werde ich einfache slices statt slice_arrays verwenden.



  • Rückgabe by-value impliziert IMHO (will ja dem Standard hier nix unterstellen), dass der copy-ctor aufgerufen wird bzw. (RVO) mindestens zugänglich sein muss.



  • Rückgabe by-value impliziert IMHO (will ja dem Standard hier nix unterstellen), dass der copy-ctor aufgerufen wird bzw. (RVO) mindestens zugänglich sein muss.

    Sehe ich genauso.
    Zumindest für die eigentliche return-Anweisung.
    Das Deklarieren einer Funktion mit value-Return alleine, erfordert ja noch kein Copy-Ctor.

    Interessant finde ich das Beispiel aus 26.3.5p2. Das deutet ja darauf hin,
    dass man den op[](slice) nur auf der linken Seite einer Zuweisung
    verwenden soll. Aber selbst wenn ich nur das mache, scheint mir 26.3.5p3 nicht erfüllbar zu sein. Irgendwer muss ja irgendwo mal ein slice_array anlegen (return). Und dieser jemand ist mit Sicherheit ein C++ Programm. Das ist schon mal schlecht. Dazu kommt in 26.3.5.1, dass die Konstruktoren nicht implementiert sein müssen, aber ohne Copy-Ctor kein value-return und zweitens hat slice_array keine Freunde. Wer soll also bitte den privaten Ctor aufrufen?

    Also meiner bescheidenen Meinung nach ist da was total kaputt.



  • Also meiner bescheidenen Meinung nach ist da was total kaputt.

    Oder dieser ganze valarray-Kram lässt sich schlicht nicht mit reinem C++ implementieren.



  • der Standard sagt nicht, dass slice_array keine friends haben darf. beim gcc sieht der private-Teil von slice_array so aus:

    private:
        friend class valarray<_T>;
        slice_array(_Array<_T>, const slice&);
    
        const size_t     _M_sz;
        const size_t     _M_stride;
        const _Array<_T> _M_array;
    
        // this constructor is implemented since we need to return a value.
        slice_array (const slice_array&);
    
        // not implemented
        slice_array ();
        slice_array& operator= (const slice_array&);
    

    (wie die Standardleute sich das ohne implementierten copy-ctor gedacht haben ist eine andere Frage)

    ok dann hat sich das wohl erledigt



  • z.b. gcc 3.3 implementierung:

    // This constructor is implemented since we need to return a value.
          slice_array(const slice_array&);
    
    friend class valarray<_Tp>;
          slice_array(_Array<_Tp>, const slice&);
    

    wo steht, das slice_array keine freunde haben darf?
    im standard steht dabei: remainder implementation defined. das reicht dohc, nicht



  • der Standard sagt nicht, dass slice_array keine friends haben darf.

    wo steht, das slice_array keine freunde haben darf?

    Jaja. Ihr habt recht. Es ist spät und ich bin der Antifrosch wenn's ums Lesen und verstehen des Holy-Standards geht.



  • aber mit dem copy ctor hattet ihr recht 🙂



  • *** blubb *** spätnachts kann man die Augen nicht mehr so gut offenhalten



  • vergiss die anderen Frauen, die bleiben alle auf der Strecke. 👎



  • vielleicht einfach mal bei comp.std.c++ nachfragen, was die da so denken?



  • Na gut, mal Zeit, mich wieder zu melden. Wen es noch interessiert:
    Im Defekt Report steht was
    und Mr. Stroustrup meint, dass er den Fehler solange nicht korrigieren will, bis das Standardkomittee das mit valarray löst.



  • Helium schrieb:

    vielleicht einfach mal bei comp.std.c++ nachfragen, was die da so denken?

    ich nehme an, die duerften eine aehnliche meinung wie josuttis haben: valarray ist (bei den momentanen vorgaben) sinnlos.
    ich nehme aber an, dass in C++0x valarray mittels expression templates implementiert werden wird (so dass valarray endlich das kann, was es koennen soll) - wenn die zeit gereicht haette, waere das ja schon bei C++98 passiert.


Anmelden zum Antworten