jambit ToiletPaper Strong Typedefs

Strong Typedefs

Problem

Viele Funktionen/Methoden, die einen Integer als Parameter nehmen, knüpfen an diesen Integer ganz besondere Erwartungen. Das kann sein: Ein Index in einer bestimmten Struktur, die ID von irgendwas, eine bestimmte physikalische Maßeinheit oder irgendwas aus Schokolade. Das Problem ist, dass f(int x) nicht sagt, "welchen Sinn" int x hat. Die möglichen Konsequenzen reichen von "merkt eh keiner" oder "Absturz/Neustart" bis zu "serious Autsch" (1).

In C++ gibt es das Schlüsselwort typedef, aber letztendlich ist es nicht viel mehr als alias in der bash, hilft also hier nicht weiter. Kommt jemand mit "ne eigene Klasse" um die Ecke, ist das vielen "zu klobig" und außerdem ... die Performance!!

Lösung

C++ erlaubt es mit seinem Template-System eigene Datentypen zu erschaffen, deren Verwendung vom Compiler überprüft werden kann (z.B. keine "impliziten casts" (2)), die sich aber zur Laufzeit weitgehend wie simple ints verhalten. Im einfachsten Fall dient das dazu, verschiedene Arten von Indizes auseinander zu halten (3); das kann aber auch erweitert werden, um typsichere Berechnungen mit SI-Einheiten durchzuführen (4) (wenn's sein muss auch "englisch imperiale" Einheiten). Der Compiler baut dabei den nötigen Code ein, um millirad in deg oder miles/h in m/s umzurechnen (und hätte so den Mars-Orbiter gerettet).

Beispiel

Die grundlegende Idee ist, ein struct (oder der Sichtbarkeit wegen eine class) mit einem einzigen Wert als Member zu erstellen. Dazu gibt es noch alle nötigen Operatoren, die man für die Handhabung braucht.

Ausgangspunkt ist folgender "unauffälliger" Code. Es fehlen noch die Deklarationen für PersonId und RoomId.

C++ class mit einem einzigen Wert als Member

Der Weg über typedef wird compilieren ...

und was anderes tun, als gedacht war:

Strong Typedefs C++

Beim gleichen Code mit PersonId als Klasse wird der Compiler bei rsc.get_room(id) aussteigen und jammern (Abbildung rechts).

Das funktioniert für kleine Anwendungsfälle ganz gut. Um aber sowohl den Linker ruhig zu halten, als auch den Methodenaufruf wegzuoptimieren, wird aus dieser class/struct noch ein template gemacht. Damit sind wir bei BOOST_STRONG_TYPEDEF angekommen (3).

Das wirkt auf den ersten Blick recht umständlich, rettet einen aber (ohne große Laufzeit-Strafen) vor "falsch verdrahteten" Integern. Wer schon mal das komplette System nach einem off-by-one Bug durchsucht hat, der weiß Bescheid.

C++ Strong Typedefs

Weiterführende Aspekte

(1) Die NASA verlor ihren 125 Mio. $ teuren Mars Climate Orbiter, weil die Ingenieure vergaßen von englischen auf metrische Einheiten umzuwandeln: http://articles.latimes.com/1999/oct/01/news/mn-17288

(2) 1996 explodierte eine Ariane 5 mitsamt ihrer Nutzlast (im Wert von ca 500 Mio $ Dollar) nachdem ein 64 Bit double in eine Funktion gesteckt wurde, die einen 16 Bit signed int erwartet. Der Wert war zu groß für die 16 Bit. http://www-users.math.umn.edu/~arnold/disasters/ariane.html

(3) Siehe BOOST_STRONG_TYPEDEF https://www.boost.org/doc/libs/1_67_0/boost/serialization/strong_typedef.hpp

(4) Siehe boost::units https://www.boost.org/doc/libs/1_67_0/libs/units/example/kitchen_sink.cpp oder nholthaus/units https://github.com/nholthaus/units#documentation

---

Autor

Hannes Lerchl / Senior Software Architect / Business Division New Business​

Zum Toilet Paper #94: Strong Typedefs (pdf)

Strong Typedefs jambit ToiletPaper

Cookie-Einstellungen

Diese Website verwendet Cookies, um Inhalte und Anzeigen zu personalisieren, Funktionen für soziale Medien anbieten zu können und Zugriffe auf die Website zu analysieren. Zudem werden Informationen zu Ihrer Verwendung der Website an Partner für soziale Medien, Werbung und Analysen weitergegeben. Die Partner führen diese Informationen möglicherweise mit weiteren Daten zusammen, die Sie ihnen bereitgestellt haben oder die sie im Rahmen Ihrer Nutzung der Dienste gesammelt haben.

Weitere Informationen finden Sie in unserer Datenschutzerklärung. Dort können Sie nachträglich auch Ihre Cookie-Einstellungen ändern.

contact icon

Kontakt aufnehmen