{"id":3182,"date":"2017-09-01T14:57:48","date_gmt":"2017-09-01T13:57:48","guid":{"rendered":"http:\/\/roboblog.fatal-fury.de\/?p=3182"},"modified":"2017-09-02T12:04:45","modified_gmt":"2017-09-02T11:04:45","slug":"c-guns-c17-extension-to-aggregate-initialization","status":"publish","type":"post","link":"http:\/\/roboblog.fatal-fury.de\/?p=3182","title":{"rendered":"C++ Guns - C++17 Extension to aggregate initialization"},"content":{"rendered":"<p>C++17 bringt ein paar tolle Sachen mit. Mit der Erweiterten Aggregat Initialisierung kann ich nun endlich meinen Lieblings Point3D Datentyp zusammenbauen.<br \/>\nDieser soll mit den Funktionen <em>x(), y() z()<\/em> Zugriff auf die einzelnen Skalare bieten, aber gleichzeitig ein Array fester L\u00e4nge sein. Damit der Compiler besser optimieren kann. Der Typ selbst soll ein Array sein, und nicht ein Array als Membervariable enthalten, um weniger tippen zu m\u00fcssen. Gleichzeitig soll aber eine Initialisierung ohne selbst geschriebenen Konstruktor m\u00f6glich sein. Der Typ muss f\u00fcr die Performance nat\u00fcrlich POD sein, darf aber niemals uninitialisiert sein. Der interne Type der Skalare muss per Templates austauschbar sein. Um Einheiten wie z.B. Meter oder Grad zu verwenden. Es sollen mit Point3D Berechnungen zur Compilezeit m\u00f6glich sein, also constexpr. Eine Ausgabe \u00fcber cout und Standard Operatoren wie + - * \/ sollen zur Verf\u00fcgung stehen.<\/p>\n<p>Ganz sch\u00f6n viele Sachen. Aber das l\u00e4sst sich alles realisieren:<\/p>\n<p>Getestet mit gcc 7.1.0 und clang-4.<br \/>\n<a href=\"http:\/\/roboblog.fatal-fury.de\/wp-content\/uploads\/2017\/09\/Point3D.cpp_.gz\"rel=\"\">Point3D.cpp.gz<\/a><\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#include &lt;iostream&gt;\r\n#include &lt;array&gt;\r\n#include &lt;type_traits&gt;\r\n\r\ntemplate&lt;typename T&gt;\r\nstruct Point3D : public std::array&lt;T,3&gt; \/\/ Typ selbst ist ein Array fester Laenge\r\n{\r\n    using value_type = T;\r\n\r\n    Point3D() = delete;\r\n\r\n    constexpr const T&amp; x() const {\r\n        return this-&gt;at(0);\r\n    }\r\n\r\n    constexpr T&amp; x() {\r\n        return this-&gt;at(0);\r\n    }\r\n\r\n    constexpr const T&amp; y() const {\r\n        return this-&gt;at(1);\r\n    }\r\n\r\n    constexpr T&amp; y() {\r\n        return this-&gt;at(1);\r\n    }\r\n\r\n    constexpr const T&amp; z() const {\r\n        return this-&gt;at(2);\r\n    }\r\n\r\n    constexpr T&amp; z() {\r\n        return this-&gt;at(2);\r\n    }\r\n};\r\n\r\n\/\/ interner Type austauschbar\r\nusing Point3Dd = Point3D&lt;double&gt;;\r\nusing Point3Df = Point3D&lt;float&gt;;\r\nusing Point3Di = Point3D&lt;int&gt;;\r\n\r\nstatic_assert(std::is_pod&lt;Point3Dd&gt;::value, &quot;Point3D is not POD&quot;);\r\n\r\ntemplate&lt;typename T&gt;\r\nstd::ostream&amp; operator&lt;&lt;(std::ostream&amp; s, const Point3D&lt;T&gt;&amp; p) {\r\n    s &lt;&lt; '(' &lt;&lt; p&#x5B;0] &lt;&lt; ' ' &lt;&lt; p&#x5B;1] &lt;&lt; ' ' &lt;&lt; p&#x5B;2] &lt;&lt; ')';\r\n    return s;\r\n}\r\n\r\ntemplate&lt;typename T, typename T2&gt;\r\nconstexpr auto operator+(const Point3D&lt;T&gt;&amp; p1, const Point3D&lt;T2&gt;&amp; p2) {\r\n    using Internal = decltype(T() + T2());\r\n    return Point3D&lt;Internal&gt; {p1&#x5B;0]+p2&#x5B;0], p1&#x5B;1]+p2&#x5B;1], p1&#x5B;2]+p2&#x5B;2]};\r\n}\r\n\r\ntemplate&lt;typename T, typename T2&gt;\r\nconstexpr auto operator-(const Point3D&lt;T&gt;&amp; p1, const Point3D&lt;T2&gt;&amp; p2) {\r\n    using Internal = decltype(T() - T2());\r\n    return Point3D&lt;Internal&gt; {p1&#x5B;0]-p2&#x5B;0], p1&#x5B;1]-p2&#x5B;1], p1&#x5B;2]-p2&#x5B;2]};\r\n}\r\n\r\n\/\/ Rest fuer dich\r\n\r\nint main() {\r\n    \/\/ niemals uninitialisiert\r\n    \/\/ error: use of deleted function \u2018Point3D&lt;T&gt;::Point3D()\r\n    \/\/Point3Dd p;\r\n\r\n    \/\/ Initialisierung ohne selbst geschriebenen Konstruktor\r\n    constexpr Point3Di p1{1, 2, 3};\r\n\r\n    \/\/ Ausfuerung zur Compilezeit\r\n    static_assert(p1.x() + p1.y() + p1.z() == 6, &quot;Oh oh&quot;);\r\n\r\n    std::cout &lt;&lt; p1 &lt;&lt; &quot;\\n&quot;;\r\n\r\n    \/\/ (Physikalische) Einheiten nutzbar (kommt bald)\r\n    \/\/Point3D&lt;SI::Meter&gt; p2 {1_m, 100_cm, 0.001_km);\r\n\r\n    constexpr Point3Dd p3{1.0, 2.0, 3.0};\r\n    \/\/ int + double = ? Der Compiler weis es\r\n    constexpr auto p4 = p1+p3;\r\n\r\n    static_assert(std::is_same&lt;decltype(p4)::value_type, double&gt;::value, &quot;int+double should be double. right?&quot;);\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>C++17 bringt ein paar tolle Sachen mit. Mit der Erweiterten Aggregat Initialisierung kann ich nun endlich meinen Lieblings Point3D Datentyp zusammenbauen. Dieser soll mit den Funktionen x(), y() z() Zugriff auf die einzelnen Skalare bieten, aber gleichzeitig ein Array fester L\u00e4nge sein. Damit der Compiler besser optimieren kann. Der Typ selbst soll ein Array sein, [&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":[],"class_list":["post-3182","post","type-post","status-publish","format-standard","hentry","category-allgemein"],"_links":{"self":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/3182","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=3182"}],"version-history":[{"count":6,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/3182\/revisions"}],"predecessor-version":[{"id":3190,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/3182\/revisions\/3190"}],"wp:attachment":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3182"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3182"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3182"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}