{"id":3343,"date":"2018-02-02T15:25:37","date_gmt":"2018-02-02T14:25:37","guid":{"rendered":"http:\/\/roboblog.fatal-fury.de\/?p=3343"},"modified":"2018-02-02T15:55:29","modified_gmt":"2018-02-02T14:55:29","slug":"c-guns-generic-data-type-design-pattern-teil-1","status":"publish","type":"post","link":"http:\/\/roboblog.fatal-fury.de\/?p=3343","title":{"rendered":"C++ Guns: Generic Data Type Design Pattern - Teil 1"},"content":{"rendered":"<p>Hmm das Problem l\u00e4sst sich vermutlich am besten anhand von Beispielen erkl\u00e4ren.<\/p>\n<p>Wie immer nehm ich gern mein Point2D Datentyp her. Es gibt ja verschiedene Wege so etwas zu implementieren.<br \/>\nEine class mit privaten x\/y Variablen und entsprechende getter\/setter. Oder ein struct mit nur public x\/y Variablen:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nstrcut Point2D {\r\n double x, y;\r\n}\r\n<\/pre>\n<p>Das Problem bei dieser Implementierung ist, dass die x\/y Variablen nicht in einem Array sind. Das mag vllt. auf den ersten Blick unn\u00f6tigt erscheinen, aber im laufe der Jahre habe ich den Zugriff auf xyz anhand von Indizes 1,2,3 \u00f6fter mal gebraucht. Die Alternative w\u00e4re also:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nstrcut Point2D {\r\n  std::array&lt;double,2&gt; xy;\r\n}\r\n<\/pre>\n<p>Aber hier fehlt dann die M\u00f6glichkeit gut auszudr\u00fccken, dass man explizit auf die x-Variable zugreifen m\u00f6chte. Wie schnell hat man doch die Index Zahlen verdreht. Eine Kombination beider Variablen ist auch M\u00f6glich:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nstrcut Point2D {\r\n  std::array&lt;double,2&gt; xy;\r\n\r\n  auto&amp; x() {\r\n    return operator&#x5B;](0);\r\n  }\r\n\r\n  auto&amp; y() {\r\n    return operator&#x5B;](1);\r\n  }\r\n}\r\n<\/pre>\n<p>Die const Varianten der x() y() habe ich jetzt mal weg gelassen. Ich m\u00f6chte jetzt auf etwas anderes hinweisen: Wie sieht es aus wenn man dieses Konstrukt in seinem Code nutzt:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n  Point2D p;\r\n  p&#x5B;0] = 10;\r\n  p&#x5B;1] = 20\r\n  cout &lt;&lt; p.x() &lt;&lt; p.y();\r\n  p.xy&#x5B;0] = 100;\r\n  p.xy&#x5B;1] = 200;\r\n  p.xy = {3,4}; ???\r\n  cout &lt;&lt; p. xy; ???\r\n  p.x() = 1000;\r\n  p.y() = 2000;\r\n<\/pre>\n<p>Also ganz ehrlich: Nein. Das ist zu viel des Guten. Zu viele Freiheitsgrade. Das verwirrt doch nur. Und wer die Qual der Wahl hat, trifft die falsche Entscheidung. Vor allem, muss man wirklich die Koordinaten \u00fcber die Funktion x() und y() setzten k\u00f6nnen? Das sieht auch ungewohnt aus. Und die extra Variable xy erscheint auch unn\u00f6tig und \u00fcberfl\u00fcssig. Zugriff auf Member, \u00fcber Funktionen, \u00fcber Index Operator. Uneinheitlich!<\/p>\n<p>Vor ein paar Monaten bin ich ja auf noch eine weitere M\u00f6glichkeit gesto\u00dfen, diesen Datentyp zu implementieren. Siehe <a href=\"http:\/\/roboblog.fatal-fury.de\/?p=3182\">C++ Guns - C++17 Extension to aggregate initialization<\/a>. Und ich muss sagen, so schlecht ist das gar nicht. Es bietet eine Menge.<\/p>\n<p>Die Idee ist, den Point2D Datentyp von einem std::array erben zu lassen. Und f\u00fcr die bessere Lesbarkeit noch getter Funktionen mit guten Namen bereit zu stellen. Durch die Vererbung IST der Point2D Datentyp ein Array. Und bietet automatisch den Index Zugriff an. Und durch die getter Funktionen bekommen die einzelnen Arraypositionen eine Semantik.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nstrcut Point2D : public std::array&lt;double,2&gt;\r\n{\r\n  const auto&amp; x() const {\r\n    return operator&#x5B;](0);\r\n  }\r\n\r\n  const auto&amp; y() const {\r\n    return operator&#x5B;](1);\r\n  }\r\n}\r\n<\/pre>\n<p>Nun gestaltet sich die Nutzung schon einfacher. Das Setzten der Werte passiert \u00fcber eine Initialisierungsliste. Das Lesen \u00fcber Funktionen. Und in den F\u00e4llen wo ein Indexzugriff besser ist, ist das nun auch realisierbar.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n  Point2D p {1,2};\r\n  cout &lt;&lt; p.x() &lt;&lt; p.y();\r\n  p&#x5B;0] = p&#x5B;1];\r\n<\/pre>\n<p>Hier habe explicit nur const getter Benutzt. Dazu sage ich sp\u00e4ter noch mehr.<\/p>\n<p>Im n\u00e4chsten Teil werde ich Versuchen, dieses Muster auf andere Datentypen anzuwenden.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hmm das Problem l\u00e4sst sich vermutlich am besten anhand von Beispielen erkl\u00e4ren. Wie immer nehm ich gern mein Point2D Datentyp her. Es gibt ja verschiedene Wege so etwas zu implementieren. Eine class mit privaten x\/y Variablen und entsprechende getter\/setter. Oder ein struct mit nur public x\/y Variablen: strcut Point2D { double x, y; } Das [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[17],"class_list":["post-3343","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\/3343","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=3343"}],"version-history":[{"count":2,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/3343\/revisions"}],"predecessor-version":[{"id":3346,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/3343\/revisions\/3346"}],"wp:attachment":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3343"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3343"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3343"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}