{"id":2826,"date":"2017-03-10T11:18:06","date_gmt":"2017-03-10T10:18:06","guid":{"rendered":"http:\/\/roboblog.fatal-fury.de\/?p=2826"},"modified":"2017-03-10T11:20:07","modified_gmt":"2017-03-10T10:20:07","slug":"c17-guns-stdoptional-part-ii","status":"publish","type":"post","link":"http:\/\/roboblog.fatal-fury.de\/?p=2826","title":{"rendered":"C++17 Guns - std::optional Part II"},"content":{"rendered":"<p>Wie schon im <a href=\"http:\/\/roboblog.fatal-fury.de\/?p=2807\">ersten Teil<\/a> berichtet, suche ich vern\u00fcnftige Anwendungsf\u00e4lle f\u00fcr std::optional.<br \/>\nDabei ist mir aufgefallen, dass schon viele Variablen implizit optional sind\/behandelt werden. Ohne, dass eine extra Variable wie z.B. bool vorhanden; vorhanden ist. Nehmen wir z.B. ein Adressbuch. Wenn der Adresszusatz nicht angegeben wurde, ist der String einfach leer. Ein std::optional&ltstd::string>> adresszusatz; w\u00e4re redundante Information. Einmal explizit im std::optional und einmal implizit im string::size.<\/p>\n<p>Bei Strings ist das einfach. Doch was ist mit Zahlen? Wenn die Hausnummer in der Adresse als Integer gespeichert w\u00e4re, und es fehlt die Information, welche Zahl ist in der Variablen hausnummer dann gespeichert? int hausnummer = 0; Null als Default? Oder lieber -1? Oder Undefiniert? Oder MAX\/MIN Integer Wert? Bei floats g\u00e4be es NaN...<\/p>\n<p>Die Idee ist, dass Zahlen einen validen Wertebereich haben. Negative Hausnummern gibt es einfach nicht. Auch ist es sehr unwahrscheinlich, dass eine Stra\u00dfe zwei Milliarden H\u00e4user hat. Die Information, ob der Wert vorhanden ist, oder nicht, ist im Wert selbst kodiert. Das widerspricht aber dem C++ Ziel, eine generalisierte Sprache zu sein. Die allgemeing\u00fcltige L\u00f6sung f\u00fcr std::optional kann daher nicht so implementiert sein, dass die 'vorhanden' oder 'nicht vorhanden' Information in der eigentlichen Variablen mit gespeichert wird. <\/p>\n<p>Wir w\u00fcrde eine Implementation von \"optional\" aussehen?<br \/>\nEine zus\u00e4tzliche boolean Variable bool vorhanden = false; w\u00e4re denkbar. Aber das kleine bool verhunzt das Speicherlayout der Klasse. Man k\u00f6nnte nur einen Pointer nehmen. Ein nullptr bedeutet, dass der Wert nicht vorhanden ist. Aber dann haben wir das owning Problem wie mit dem std::shared_ptr auch. Was ist, wenn std::optional eine Kopie der Variable h\u00e4lt? Problem 1 gel\u00f6st. Problem 2: Welcher Wert hat denn das optional, wenn es kein Wert gibt? Ein default Wert. Welcher? Nicht jede Klasse hat einen default ctor oder kann \u00fcberhaupt einen haben.<\/p>\n<p>Ich sehe, default Werte, default ctors und std::optional und string::size (vector::size) haben viel gemeinsam. Da kommt auch gleich die RAII (Ressourcenbelegung ist Initialisierung) Idee daher. Man schreibt nicht einfach std::string s; int i; oder int i=0; Sondern belegt die Variable gleich mit einem g\u00fcltigen Wert.<br \/>\nstd::string s = func(); int i = func(); Was aber, wenn func() keinen Wert zur\u00fcck liefern kann, weil es keinen gibt? Das muss nicht gleich ein Fehler sein. Datens\u00e4tze sind nunmal nie vollst\u00e4ndig. Das ist das selbe Problem wie oben besprochen.<\/p>\n<p>Ich pers\u00f6nlich f\u00fchle mich nicht wohl mit dem Gedanken, \u00fcberall im Code optionals zu haben, die existieren k\u00f6nnten, oder nicht. Die Variationen gehen exponentiell mit der Anzahl der Variablen. Das will niemand und ich bezweifle, dass man das \u00fcberhaupt braucht. <\/p>\n<p>Also mir kommen da zwei M\u00f6glichkeiten in den Sinn. Der Erste, wie oben schon angedeutet, einen g\u00fcltigen Wertebereich definieren. Viele Variablen bilden ja irgendwas aus der Realit\u00e4t ab. Z.B. eine H\u00f6henangabe auf der Welt. Was ist der h\u00f6chste Punkt? Irgendwas mit 8000m. Was ist der tiefste Punkt? Irgendwas mit -11000m. Man kann also eine noDepthValue definieren mit -99999m und ihn als default Wert f\u00fcr H\u00f6henangaben nutzen. Das l\u00e4sst sich mit dem Typesystem auch leicht implementieren. using Height_t = double; Oder beliebig kompliziert. Das Funktioniert mit Koordinaten genauso. Im sph\u00e4rischen System gibt es keinen Rechtswert gr\u00f6\u00dfer als 180grad. Vorraussetzung daf\u00fcr ist, dass das \"Ding\" in der Realit\u00e4t auch genau diesen Typ in C++ bekommt. Also kein double x; mehr. Lieber Coordinate x; So k\u00f6nnen auch gleich SI Einheiten mit einbezogen werden. Aber das ist ein anderes Thema. Das ist auch gleich Performant und SSE freut sich, wenn die Daten alignt rein kommen.<\/p>\n<p>Ist die erste M\u00f6glichkeit schon sehr Dom\u00e4nenspeziell, brauchen wir auch eine allgemeing\u00fcltige C++ Philosophie L\u00f6sung. Hier orientiere ich mich an std::string::size bzw std::vector::size. Wie schon oben Erw\u00e4hnt, ist die Information, ob ein String leer ist oder nicht, in der size Variable in der std::string Klasse abgelegt. (Und nicht, wie bei C, im den eigentlichen String Daten selbst). Was hindert mich daran, das f\u00fcr alle anderen Daten auch zu tun? F\u00fcr das Beispiel nehme ich nochmal die Adresse.<\/p>\n<pre><code>\r\nstruct Name {\r\n  string vorname, nachname;\r\n};\r\nstruct Adresse {\r\n  vector&ltName> name;\r\n  vector&ltstring> strasse;\r\n  vector&ltint> hausnummer;\r\n  vector&ltstring> stadt;\r\n};\r\n<\/code><\/pre>\n<p>Na, ist das nichts? ;) Ich finde das sehr realistisch. Hat die Adresse keinen hausnummer, so ist der vector einfach leer. Ein leerer Vector f\u00fchrt bei keiner Library zu Problemen. Jede for() Schleife ist gl\u00fccklich damit. Da steckt das if(vorhanden) schon drin. Und wer sagt denn bitte sch\u00f6n, dass eine Person nur einen Namen haben darf? Wenn man heiratet, \u00e4ndert sich der Nachname. Wenn man die Identit\u00e4t wechselt, \u00e4ndert sich der Name. Die Freunde nennen einem meist nicht beim vollen Namen. Im Internet hat man Nicks. Man kann sich auch als jemand anderes ausgeben. In anderen L\u00e4ndern wird sein Name wom\u00f6glich leicht anders geschrieben und ausgesprochen. Soll ich weiter machen? Das selbe gilt nat\u00fcrlich auch f\u00fcr die restlichen Variablen. Hier w\u00e4re also sogar ein Zeitfaktor mit implementiert ;)<br \/>\nAbsolut \u00fcbertrieben und Anwendungsfern? Ja aber, genau das wollen wir doch mit c++.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wie schon im ersten Teil berichtet, suche ich vern\u00fcnftige Anwendungsf\u00e4lle f\u00fcr std::optional. Dabei ist mir aufgefallen, dass schon viele Variablen implizit optional sind\/behandelt werden. Ohne, dass eine extra Variable wie z.B. bool vorhanden; vorhanden ist. Nehmen wir z.B. ein Adressbuch. Wenn der Adresszusatz nicht angegeben wurde, ist der String einfach leer. Ein std::optional&#038;ltstd::string>> adresszusatz; w\u00e4re [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[17],"class_list":["post-2826","post","type-post","status-publish","format-standard","hentry","category-allgemein","tag-cpp"],"_links":{"self":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/2826","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2826"}],"version-history":[{"count":4,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/2826\/revisions"}],"predecessor-version":[{"id":2830,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/2826\/revisions\/2830"}],"wp:attachment":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2826"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2826"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2826"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}