Returntyp dynamisch ändern



  • Wenn es nur um Geschwindigkeit geht – d.h. eine Prüfung wäre immer sinnvoll, aber manchmal zu langsam – würde ich wirklich assert() nehmen. Policies stehen nur zur Diskussion, wenn die Programmsemantik betroffen ist.

    Und Loki::SmartPtr ist mit seinen fünf Policies massiv overengineered, trotzdem kann man die Klasse für einfache Spezialfälle nicht gebrauchen (Beispiel siehe hier). Ich habe mir für die Fälle, in denen std::unique_ptr und std::shared_ptr nicht geeignet sind, eigene Smart-Pointer geschrieben. Das betrifft vor allem Implementierungen mit Deep-Copy-Semantik.



  • Einige meiner Klassen benutzen OpenGL. Das Checken lässt sich also nicht durch ein einfaches assert() erledigen, sondern der untersuchte Wert muss mit z.B. glGetIntegerv ermittelt werden. Ein assert macht hier vermutlich keinen Sinn, da wahrscheinlich der Aufruf von glGetIntegerv am meisten Zeit braucht. Hier macht es doch Sinn, durch ein Policy festzulegen, ob gecheckt werden soll oder nicht, oder?



  • Wieso sollte das ein Problem mit dem assert sein? Im Debug-Modus spielt die Zeit keine Rolle (und da du sowieso checken willst, ist dein Aufruf auch notwendig), im Release wird der assert()-Aufruf sowieso vom Präprozessor wegoptimiert.



  • Das ist mir klar.
    Wer sagt denn, ob ich Checken will? glGetIntegerv kann nicht wegoptimiert werden.



  • allestester schrieb:

    Das ist mir klar.
    Wer sagt denn, ob ich Checken will? glGetIntegerv kann nicht wegoptimiert werden.

    Klar, die Funktion kannst du nicht optimieren - aber im ungecheckten Ablauf mußt du sie auch nicht aufrufen, wenn du sie nicht benötigst.



  • Also macht es dann an der Stelle Sinn, ein CheckingPolicy zu verwenden.



  • allestester schrieb:

    Also macht es dann an der Stelle Sinn, ein CheckingPolicy zu verwenden.

    Wenn es nur darum geht, Programmierfehler zu finden, nein. Ich sehe dein Problem wirklich nicht. Es ist ganz einfach:

    • Für zeitintensive Überprüfungen zu Debugging-Zwecken, die keinen Einfluss auf die Semantik des Programms haben, nimmst du assert . Im Release-Modus sind alle Assertions ausgeschaltet, du hast also keinen Overhead.
    • Sonst... nimmst du nicht assert 🤡


  • OpenGL Errors können auch außerhalb des Debuggings auftreten. Code, der bei mir auf dem PC läuft, muss nicht auf meinem Lappi laufen. Allein schon wegen der verschiedenen Hardware.



  • Okay, Laufzeitfehler sind wieder ein anderes Thema als Programmierfehler. Dann kann so eine Policy Sinn machen, aber ich würds damit nicht übertreiben. Denk dran, dass du jede Policy in den Typen eingravierst und dadurch leicht verschiedene, inkompatible Template-Instanziierungen erzeugst. Wenn es nur darum geht, eine Zuweisung zu überprüfen, kannst du auch eine Funktion

    bool CheckedAssign(SmartPtr& dest, const SmartPtr& source);
    

    schreiben.

    P.S. Noch was:

    allestester schrieb:

    Die Zuweisungsmethode gibt einen bool zurück, der den Erfolg der Ausführung verrät. Wenn ich jetzt aber einen NotChecked-SmartPointer habe, macht es keinen Sinn, wenn die Zuweisungsmethode trotzdem noch einen bool zurückgibt.

    Meinst du damit den SmartPtr::operator= ? Der sollte nicht bool , sondern SmartPtr& zurückgeben...



  • allestester schrieb:

    Einige meiner Klassen benutzen OpenGL. Das Checken lässt sich also nicht durch ein einfaches assert() erledigen, sondern der untersuchte Wert muss mit z.B. glGetIntegerv ermittelt werden.

    Ich werf mal das Stichwort Exceptions in den Raum...



  • @Nexus:
    Okay, dann werde ich mir mal genauer überlegen, wo ich asserts anstatt Policies verwende. Vergiss mein Beispiel, das war mehr als schlecht 😃

    @dot:
    Ich benutze nicht gerne Exceptions. Ich finde sie zu unhandlich.



  • Der grosse Vorteil von Exceptions besteht darin, dass du den Anwendercode frei von Fehlerbehandlung halten kannst. Du musst nicht jede Anweisung einzeln auf ihren Erfolg prüfen, ausserdem brauchst du den Status nicht umständlich über mehrere Funktionen hinweg hochzureichen.

    Schau dir vielleicht den Artikel zu modernem Exceptionhandling an, er erklärt die Thematik wirklich gut.



  • allestester# schrieb:

    @dot:
    Ich benutze nicht gerne Exceptions. Ich finde sie zu unhandlich.

    Sry, aber daraus kann man eigentlich nur schließen dass du sie nicht verstanden hast 😉

    Siehe was Nexus sagt 🙄



  • Ich hab noch kein ganzes Buch über Exception-Handling gelesen, nur ein Kapitel eines Buches. Vielleicht sollte ich mich damit mal ein bisschen beschäftigen.



  • Nexus schrieb:

    P.S. Noch was:

    allestester schrieb:

    Die Zuweisungsmethode gibt einen bool zurück, der den Erfolg der Ausführung verrät. Wenn ich jetzt aber einen NotChecked-SmartPointer habe, macht es keinen Sinn, wenn die Zuweisungsmethode trotzdem noch einen bool zurückgibt.

    Meinst du damit den SmartPtr::operator= ? Der sollte nicht bool , sondern SmartPtr& zurückgeben...

    Falls das schon erklärt wurde sorry, aber: was für ein Smart-Pointer ist das denn, dass der Zuweisungsoperator fehlschlagen kann? 😕

    Selbst wenn es z.B. um eine Never-Null Garantie geht, kann der Zuweisungsoperator nicht fehlschlagen, sofern
    a) man im Konstruktor überprüft ob ein Nullpointer übergeben wurde, und falls ja, brav abort()ed oder eine Exception wirft und
    b) der Zuweisungsoperator nicht mit rohen Zeigern funktioniert

    Dinge die (auf Grund von Laufzeitfehlern) fehlschlagen können, haben IMO in einem Smart-Pointer nix verloren. Und Dinge die nur auf Grund von Programmierfehlern fehlschlagen können, würde ich mit assert() oder abort() behandeln.


Anmelden zum Antworten