range-checked vector



  • Hallo,

    ich hätte gerne einen range-checked vector, bei dem bei Aufruf des []-Operators automatisch at() aufgerufen wird. Muss man das sich per Hand programmieren oder gibt es das schon in der Boost/STL/sonstwo?



  • Was spricht dagegen, at() aufzurufen?



  • Tachyon schrieb:

    Was spricht dagegen, at() aufzurufen?

    Das wird mir zu unübersichtlich und ich möchte per Präprozessoranweisung im ganzen Programm zwischen normalen und range-checked Vektoren umschalten können.



  • ingobulla schrieb:

    Das wird mir zu unübersichtlich

    Dann bleibt dir vermutlich nichts anderes übrig als die Funktionalität selber einzubauen.

    und ich möchte per Präprozessoranweisung im ganzen Programm zwischen normalen und range-checked Vektoren umschalten können.

    Warum nicht per typedef?



  • pumuckl schrieb:

    und ich möchte per Präprozessoranweisung im ganzen Programm zwischen normalen und range-checked Vektoren umschalten können.

    Warum nicht per typedef?

    stimmt, das wäre natürlich das angemessenere Sprachelement



  • ingobulla schrieb:

    ...ich möchte per Präprozessoranweisung im ganzen Programm zwischen normalen und range-checked Vektoren umschalten können.

    Dann nimm doch den Compilerschalter "-O" (oder was Dein Compiler gerade so hergibt).... es kann gut sein, dass Deine STL das bereits anbietet (vector::operator[] in "Debug-Modus" checked - und sonst unchecked).

    Warum das Rad neu erfinden ?

    Gruß,

    Simon2.



  • Simon2 schrieb:

    Dann nimm doch den Compilerschalter "-O" (oder was Dein Compiler gerade so hergibt).... es kann gut sein, dass Deine STL das bereits anbietet (vector::operator[] in "Debug-Modus" checked - und sonst unchecked).

    Ich benutze gcc und verwende den maximalen Debug-Level, ohne dass ein Range-Check erfolgt. Von daher scheint das mit gcc nicht zu funktionieren.



  • Leite von vector ab, und überlade den [] - Operator.



  • Belli schrieb:

    Leite von vector ab, und überlade den [] - Operator.

    Schlechte Idee, da std::vector nicht als Basisklasse konzipiert ist (z.B. kein virtueller Destruktor).

    Benutze at() , wenn du Range-Checks willst, dafür ist die Funktion da. Oder programmier halt so, dass es keine Checks braucht...



  • Belli schrieb:

    Leite von vector ab, und überlade den [] - Operator.

    Der wird dann aber eher überdeckt und net überladen.



  • Nexus schrieb:

    Belli schrieb:

    Leite von vector ab, und überlade den [] - Operator.

    Schlechte Idee, da std::vector nicht als Basisklasse konzipiert ist (z.B. kein virtueller Destruktor).

    Stroustrup empfiehlt das in "Die C++ Programmiersprache".



  • Nexus schrieb:

    Belli schrieb:

    Leite von vector ab, und überlade den [] - Operator.

    Schlechte Idee, da std::vector nicht als Basisklasse konzipiert ist (z.B. kein virtueller Destruktor).

    btw ... spielt das nicht nur dann eine Rolle, wenn ich einen Zeiger auf einen Vektor anlege und den dann auf ein Objekt meiner abgeleiteten Klasse zeigen lasse?



  • Belli schrieb:

    spielt das nicht nur dann eine Rolle, wenn ich einen Zeiger auf einen Vektor anlege und den dann auf ein Objekt meiner abgeleiteten Klasse zeigen lasse?

    Jupp und wenn das abgeleitete Objekt keine zusätzlichen Member-Variablen beinhaltet und einen "leeren" Destruktor hat, sollte es bei allen gängigen Compilern meiner Meinung nach keine Probleme geben (schön ist's trotzdem nicht).



  • Belli schrieb:

    Stroustrup empfiehlt das in "Die C++ Programmiersprache".

    Okay, dann kann wohl kein Gegenargument mehr gebracht werden. :p

    Wenn schon, würde ich den std::vector wrappen, also als Member verwenden. Aber beide Ansätze sind weitaus übertrieben, wenn man bedenkt, was deren Anstoss war - aus Ästhetikgründen nicht at() statt operator[] verwenden zu wollen. 🙄



  • Nexus schrieb:

    ...aus Ästhetikgründen nicht at() statt operator[] verwenden zu wollen. 🙄

    Naja, nucht NUR das.
    Er wollte ja auch "...per Compilerschalter range checking an- und ausschalten..." (nicht, dass ich das ein erstrebenswerteres Ziel fände, aber das ist schon ein wenig mehr als reine Kosmetik 😃 ).

    Gruß,

    Simon2.



  • #ifdef MIT_CHECK
    #define LIPPENSTIFT .at(
    #define WIMPERNTUSCHE )
    #else
    #define LIPPENSTIFT [
    #define WIMPERNTUSCHE ]
    #endif
    
    // ...
    
    meinVector LIPPENSTIFT 3 WIMPERNTUSCHE = meinVector LIPPENSTIFT 10 WIMPERNTUSCHE;
    

    Dann passt das auch mit der Kosmetik.

    SCNR



  • Nexus schrieb:

    Belli schrieb:

    Stroustrup empfiehlt das in "Die C++ Programmiersprache".

    Okay, dann kann wohl kein Gegenargument mehr gebracht werden. :p

    Wenn schon, würde ich den std::vector wrappen, also als Member verwenden. Aber beide Ansätze sind weitaus übertrieben, wenn man bedenkt, was deren Anstoss war - aus Ästhetikgründen nicht at() statt operator[] verwenden zu wollen. 🙄

    Also für diesem konkreten Fall würde ich wohl private von Vektor erben (was ja ebenfalls einer Aggregation entspricht), und alles, was benötigt wird über using Direktiven wieder sichtbar machen bzw. den operator[] überdecken.

    Ganz prinzipiell halte ich das aber immer noch für einen schlechten Ansatz. Ich würde die Rangechecks wohl eher über das assert() -Makro lösen. Das kann man dann auch einfach im Release-Mode per Makro ausschalten.



  • Mal abgesehn von den bisherigen Diskussionen mal eine kleine Betrachtung ob das überhaupt sinnvoll ist:

    - Wenn Range-Checks eingeschaltet sind, muss eine Exceptionbehandlung her, sonst hat man gegenüber der Version ohne Range-checks keine nennenswerten Vorteile: so oder so schmiert das Programm ab.
    - Hat man die Range-Checks dann ausgeschaltet, braucht man die Exceptionbehandlung auch nicht mehr. auf der anderen Seite hat man dann wohl durch andere Methoden sichergestellt, dass die Indizes jeweils gültig sind (sonst würd einem das Programm ja um die Ohren fliegen)

    Die Entscheidung, ob man at() oder op[] benutzt, ist also eine Designentscheidung die sich auch auf den umliegenden Code auswirkt, nicht nur auf die Aufrufe selbst. Das mit einem #define "mal eben" hin- und hertriggern zu wollen ist also recht sinnfrei.

    Wenns dir nur darum geht während der Entwicklung die Range zu überprüfen, nutz assert(), dazu ist das da (und wird im Releasemodus automatisch weggetriggert)



  • pumuckl schrieb:

    Warum nicht per typedef?

    Ich habe es gerade mit typedef versucht und dabei festgestellt, dass der Standard ja so was wie

    template<class T> typedef vector<T> RVec;
    

    gar nicht erlaubt. Kann man das irgendwie anders mit typedef umsetzen oder muss man doch Präprozessor-Direktiven nutzen?



  • Hast Du die letzten paar Posts auch mal gelesen?


Log in to reply