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

Wir verwenden Cookies, um unsere Webseite für Sie zu optimieren. Mit dem Besuch unserer Webseite erklären Sie sich damit einverstanden. // Our website is using cookies to improve your experience. By continuing to browse the site, you are agreeing to our use of cookies.

Weitere Informationen finden Sie in unserer Datenschutzerklärung. // For more information, please refer to our privacy policy.