2d array (vector*vector) schnell initialisieren



  • Bashar schrieb:

    Achso, du willst a[x][y] schreiben und das soll a.operator[](x,y) bedeuten?

    Jupp.

    Und wie soll der Compiler das von a.operator[](x).operator[](y) unterscheiden?

    Gar nicht. Das ist dann ambig, oder es wird immer der mit den meisten Argumenten genommen.





  • Bashar schrieb:

    Ich finds aber sprachphilosophisch hässlich, Ausdrücke zu haben, die eigentlich keine sind.

    Ja, das stört mich auch.


    Aber mit der bisherigen Lösung von Proxys geht das auch nicht so richtig, man müsste dazu operator& überladen, so dass man einen entsprechenden Pointer bekommt.
    Alles nicht das Wahre.



  • Nathan schrieb:

    Aber es wäre afaik kein Problem, dem operator[] beliebig viele Argumente zu geben.

    int operator[](int x, int y);
    

    Das entspricht dann:

    arr[x][y]
    

    Naja, das fände ich jetzt schlecht um ehrlich zu sein. Erstens wegen mehrdeutigkeit und zweitens würde man dann ja wieder nicht sehen dass es sich (explizit) um eine "viereckige" 2-dimensionale Datenstruktur handelt. Schließlich lässt sich vector<vector<T>> genauso indizieren, stellt aber etwas völlig anderes dar.

    Wenn schon fände ich sowas gut:

    struct matrix {
        matrix(int rows, int cols) { /* Implementierung */ }
        int &operator[](int row, int col) { /* Implementierung */ }
    };
    
    // Und dann so benutzen:
    int main() {
        matrix mat(3, 3);
        mat[0, 0] = 1;
        mat[1, 0] = 2;
        mat[2, 0] = 3; // etc.
    }
    

    Fände ich cool 🙂
    Dann würde man schön den Unterschied sehen und es wäre konsistent zu 1D Containern.



  • Wie gesagt, das kollidiert mit der bestehenden Syntax.



  • Bashar schrieb:

    Wie gesagt, das kollidiert mit der bestehenden Syntax.

    Ja dieser blöde Komma-Operator 👎
    Verwendet den überhaupt jemand außerhalb von for-Schleifen etc.?

    Könnte man ja vielleicht so machen dass man wie beim operator() auch extra Klammern angeben muss wenn man den Komma-Operator da verwenden will. Also so:

    mat(i, j); // operator()(int, int)
    mat((i, j)); // operator()(int)
    mat[i, j]; // operator[](int, int)
    mat[(i, j)] // operator[](int)
    

    Wäre auch irgendwie logischer. Die Frage wäre dann vermutlich wieviel alter Code durch so eine Umstellung kaputt gehen würde... Denke aber die wenigsten setzen einen Komma-Operator so innerhalb von eckigen Klammern ein 🤡



  • Nathan schrieb:

    Aber mit der bisherigen Lösung von Proxys geht das auch nicht so richtig, man müsste dazu operator& überladen, so dass man einen entsprechenden Pointer bekommt.
    Alles nicht das Wahre.

    arr.at(y,x) übersetzt.



  • happystudent schrieb:

    Ja dieser blöde Komma-Operator 👎
    Verwendet den überhaupt jemand außerhalb von for-Schleifen etc.?

    Arcoth hatte neulich eine nette Verwendung mit SFINAE, afair sizeof(foo,0).

    Könnte man ja vielleicht so machen dass man … extra Klammern angeben muss wenn man den Komma-Operator da verwenden will. Also so:

    mat(i, j); // operator()(int, int)
    mat((i, j)); // operator()(int)
    mat[i, j]; // operator[](int, int)
    mat[(i, j)] // operator[](int)
    

    [/quote]
    Compilerbaue könnten eine Warnung einbauen, wenn man um einen Kommaoperatorausdruck keine Klammern macht.



  • volkard schrieb:

    Nathan schrieb:

    Aber mit der bisherigen Lösung von Proxys geht das auch nicht so richtig, man müsste dazu operator& überladen, so dass man einen entsprechenden Pointer bekommt.
    Alles nicht das Wahre.

    arr.at(y,x) übersetzt.

    Nein, &arr[y] geht nicht wie bei nativen Arrays.

    volkard schrieb:

    happystudent schrieb:

    Ja dieser blöde Komma-Operator 👎
    Verwendet den überhaupt jemand außerhalb von for-Schleifen etc.?

    Arcoth hatte neulich eine nette Verwendung mit SFINAE, afair sizeof(foo,0).

    Nicht nur Arcoth, sizeof(foo, 0) oder decltype(foo, 0) kann man ständig gebrauchen.
    Außerdem gibts da noch das for-each-parameter-pack:

    char dummy[] = {(func(bla), '\0')..., '\0'};
    

  • Mod

    char dummy[] = {(func(bla), '\0')..., '\0'};
    

    Das ist nicht so optimal.

    std::initialier_list<int>{ (func(bla),0)... };
    

    Oder mit

    struct evaluate{ template <typename... A> constexpr evaluate(A&&...) {} };
    
    evaluate{ func(bla)... };
    


  • Nathan schrieb:

    Nein, &arr[y] geht nicht wie bei nativen Arrays.

    Ach, Du willst wirklich auf einem 2D-Array &arr[y] machen. Ok, sehe den Bedarf nicht. Zu viele Implementierungen könnten auch keine sinnvolle getRow(y) anbieten.
    &arr[y] ist nur ein Hack, den man nehmen kann, wenn man das Speicherlayout zufällig genau kennt und es sich nie wieder ändern wird. &arr[0][y] dürfte gehen.



  • Arcoth schrieb:

    char dummy[] = {(func(bla), '\0')..., '\0'};
    

    Das ist nicht so optimal.

    std::initialier_list<int>{ (func(bla),0)... };
    

    Oder mit

    struct evaluate{ template <typename... A> constexpr evaluate(A&&...) {} };
    
    evaluate{ func(bla)... };
    

    Und wenn ich es sequenced haben will?

    volkard schrieb:

    Nathan schrieb:

    Nein, &arr[y] geht nicht wie bei nativen Arrays.

    Ach, Du willst wirklich auf einem 2D-Array &arr[y] machen. Ok, sehe den Bedarf nicht. Zu viele Implementierungen könnten auch keine sinnvolle getRow(y) anbieten.
    &arr[y] ist nur ein Hack, den man nehmen kann, wenn man das Speicherlayout zufällig genau kennt und es sich nie wieder ändern wird. &arr[0][y] dürfte gehen.

    Nee, brauchen würd ich das auch nicht.
    Aber das ist halt der Nachteil, dass arr[x][y], eine expression ist, anstatt wie sonst auch zwei verschiedene.


  • Mod

    Und wenn ich es sequenced haben will?

    Gut geschlafen?



  • Arcoth schrieb:

    Und wenn ich es sequenced haben will?

    Gut geschlafen?

    Function call von evaluate ist definitiv nicht sequenced. Damit meine ich Seiteneffekte von func.
    Und das Proposal dafür ist ein Proposal und afaik nirgendwo implementiert.
    Worauf willst du also hinaus?



  • Nathan schrieb:

    Aber das ist halt der Nachteil, dass arr[x][y], eine expression ist, anstatt wie sonst auch zwei verschiedene.

    Versteh das Problem weiterhin nicht.
    arr.at(y,x) ist ja *ein* Ding, so auch arr[y][x]. arr[y] hat überhaupt keine Bedeutung.

    T& Sparse::at(int y,int x){
    //   return maps[y][x];
    //   return queue[y][x];
    //   return uoMaps[y][x];
       return map[make_pair(y,x)];
       return uoMap[make_pair(y,x)];
    }
    


  • volkard schrieb:

    Nathan schrieb:

    Aber das ist halt der Nachteil, dass arr[x][y], eine expression ist, anstatt wie sonst auch zwei verschiedene.

    Versteh das Problem weiterhin nicht.
    arr.at(y,x) ist ja *ein* Ding, so auch arr[y][x]. arr[y] hat überhaupt keine Bedeutung.

    Hier sollte jetzt eigentlich ein Argument stehen, dass überladene Operatoren ansonsten auch die Semantiken von built-ins haben, aber dann vielen mir , && und || ein, und ich musste dir zustimmen. Das ist kein Problem.


  • Mod

    Function call von evaluate ist definitiv nicht sequenced. Damit meine ich Seiteneffekte von func.

    Ich nehme an, du meinst die Auswertungsreihenfolge der Argumente?

    N3337 [dcl.init.list]/4 schrieb:

    Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions (14.5.3), are evaluated in the order in which they appear. That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list.

    x

    Und das Proposal dafür ist ein Proposal und afaik nirgendwo implementiert.

    Welches Proposal?



  • Arcoth schrieb:

    Function call von evaluate ist definitiv nicht sequenced. Damit meine ich Seiteneffekte von func.

    Ich nehme an, du meinst die Auswertungsreihenfolge der Argumente?

    Ja.

    N3337 [dcl.init.list]/4 schrieb:

    Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions (14.5.3), are evaluated in the order in which they appear. That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list.

    evaluate{ func(bla)... }; ist AFAIK kein initializer-clause.

    Und das Proposal dafür ist ein Proposal und afaik nirgendwo implementiert.

    Welches Proposal?

    Das Proposal. N4228

    Da sind auch so tolle Sachen wie Modules, operator.(), Ranges, Default comparision, Atomic Smart Pointer, Operator assert, uvm.
    C++17 wird awesome.


  • Mod

    evaluate{ func(bla)... }; ist AFAIK kein initializer-clause.

    evaluate{ func(bla)... } ist selbstverständlich keine initializer-clause, jedenfalls nicht ohne Kontext.
    Aber func(bla)... sind welche. Und zwar für die initializer list mit der die Temporary initialisiert wird.



  • Arcoth schrieb:

    evaluate{ func(bla)... }; ist AFAIK kein initializer-clause.

    evaluate{ func(bla)... } ist selbstverständlich keine initializer-clause, jedenfalls nicht ohne Kontext.
    Aber func(bla)... sind welche. Und zwar für die initializer list mit der die Temporary initialisiert wird.

    Dann hält sich GCC scheinbar nicht daran.
    http://ideone.com/ueQiBN


Anmelden zum Antworten