{"id":3369,"date":"2018-02-27T16:48:34","date_gmt":"2018-02-27T15:48:34","guid":{"rendered":"http:\/\/roboblog.fatal-fury.de\/?p=3369"},"modified":"2018-02-28T10:09:23","modified_gmt":"2018-02-28T09:09:23","slug":"c-guns-templated-class-specialization-where-template-argument-is-a-template","status":"publish","type":"post","link":"http:\/\/roboblog.fatal-fury.de\/?p=3369","title":{"rendered":"C++ Guns: Templated class specialization where template argument is a template"},"content":{"rendered":"<p>Okay das ist mit Abstand das krasseste was ich seit langem mit Templates gemacht habe, obwohl die Aufgabe doch recht klar und einfach ist. Der Code ist von der Syntax her auch noch irgendwo okay. Naja, vllt. auch nicht.<\/p>\n<p>Ich habe meine Experimentelle Graph Klasse mit entsprechenden Iteratoren. Datencontainer und Algorithmus trennen und mit Iteratoren wieder verbinden klappt btw. ziemlich gut. Da hat er 1984 was richtig gemacht.<\/p>\n<p>Seit C++17 gibt es std::distance(first, last) welche die Anzahl der Elemente zwischen first und last zur\u00fcck gibt. Die m\u00f6chte ich nutzen. Dazu m\u00fcssen meine Iteratoren std kompatibel werden. Genauer gesagt m\u00fcssen die Anforderungen an einem <em>InputIterator<\/em> erf\u00fcllt werden. Hierf\u00fcr muss man <em>std::iterator_traits<InputIt><\/em> spezialisieren. Und die 5 Variablen <em>difference_type,  value_type, pointer, reference, iterator_category<\/em> erstellen und auch hoffentlich richtig belegen.<\/p>\n<p>Funktionen im std namespace zu \u00fcberladen, oder template zu spezialisieren ist in der Regel nicht erlaubt, aber bei std::iterator_trais explizit gew\u00fcnscht. Man muss nur darauf achten den Code nicht in irgendeinem Namespace zu schreiben, sonst wird er vom Compiler nicht gefunden.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#include &lt;iterator&gt;\r\n\r\ntemplate&lt;&gt;\r\nstruct std::iterator_traits&lt;MyIterator&gt; {\r\n    using Iterator          = ...;\r\n    using difference_type   = ...;\r\n    using value_type        = ...;\r\n    using pointer           = ...;\r\n    using reference         = ...;\r\n    using iterator_category = ...;\r\n};\r\n<\/pre>\n<p>So weit so einfach, dumm nur, wenn die Klasse MyIterator wiederrum eine Template Klasse ist. Also braucht man eine Template Klassen Spezialisierung mit einer Template Klasse. Okay das ist schon halb WTF. Wir wollen also ein Template spezialisieren, so dass die Template Parameter gesetzt sind, aber die Parameter sind selbst wieder Template. Die Spezialisierung ist also garnicht speziell, nur ein bisschen. <\/p>\n<p>Wenn man am Ende noch an das Keyword <em>typename<\/em> denkt (der Compiler erinnert einem gut daran), da wir ja alles vertemplated haben, schaut es am Ende so aus:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\ntemplate&lt;typename Graph&gt;\r\nstruct std::iterator_traits&lt;cpl::graph::ConnNodeIterator&lt;Graph&gt;&gt; {\r\n    using Iterator = cpl::graph::ConnNodeIterator&lt;Graph&gt;;\r\n    using difference_type   = typename Iterator::difference_type;\r\n    using value_type        = typename Iterator::value_type;\r\n    using pointer           = typename Iterator::pointer;\r\n    using reference         = typename Iterator::reference;\r\n    using iterator_category = typename Iterator::iterator_category;\r\n};\r\n<\/pre>\n<p>Update: Habe nochmal nachgeschaut. Eine Template Spezialisierung beginnt normalerweise mit <em>template<><\/em>. Aber in diesem Fall muss man das <em>template<><\/em> mit Parameter f\u00fcllen. Die Spezialisierung funktioniert dennoch :D<\/p>\n<p>Alles nur damit ich das hier so bequem schreiben kann:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nNodeID ID = 0;\r\ngraph.connNodeRange(ID).size();\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Okay das ist mit Abstand das krasseste was ich seit langem mit Templates gemacht habe, obwohl die Aufgabe doch recht klar und einfach ist. Der Code ist von der Syntax her auch noch irgendwo okay. Naja, vllt. auch nicht. Ich habe meine Experimentelle Graph Klasse mit entsprechenden Iteratoren. Datencontainer und Algorithmus trennen und mit Iteratoren [&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-3369","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\/3369","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=3369"}],"version-history":[{"count":5,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/3369\/revisions"}],"predecessor-version":[{"id":3374,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/3369\/revisions\/3374"}],"wp:attachment":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3369"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3369"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3369"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}