{"id":3508,"date":"2018-06-02T10:30:27","date_gmt":"2018-06-02T09:30:27","guid":{"rendered":"http:\/\/roboblog.fatal-fury.de\/?p=3508"},"modified":"2022-02-16T11:22:49","modified_gmt":"2022-02-16T10:22:49","slug":"c-guns-convert-tuple-to-parameter-pack","status":"publish","type":"post","link":"http:\/\/roboblog.fatal-fury.de\/?p=3508","title":{"rendered":"C++ Guns: convert tuple to parameter pack"},"content":{"rendered":"<p><a href=\"http:\/\/roboblog.fatal-fury.de\/?p=3474\">Part1: print std::array with std:integer_sequence<\/a><br \/>\n<strong>Part2: convert tuple to parameter pack<\/strong><br \/>\n<a href=\"http:\/\/roboblog.fatal-fury.de\/?p=3514\">Part 3: print std::array with std::apply and fold<\/a><br \/>\n<a href=\"http:\/\/roboblog.fatal-fury.de\/?p=3529\">Part 4: fold over std::tuple und erzeugten Assembler Code<\/a><br \/>\n<a href=\"http:\/\/roboblog.fatal-fury.de\/?p=3538\">Part 5: fold over std::tuple of std::vector of Types ...<\/a><br \/>\n<a href=\"http:\/\/roboblog.fatal-fury.de\/?p=3617\">Part 6: apply generic lambda to tuple<\/a><br \/>\n<a href=\"http:\/\/roboblog.fatal-fury.de\/?p=4994\">Part 7: Play with std::tuple and std::apply<\/a><\/p>\n<p>Guckst du hier <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/parameter_pack\">https:\/\/en.cppreference.com\/w\/cpp\/language\/parameter_pack<\/a><br \/>\nund hier <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/fold\">https:\/\/en.cppreference.com\/w\/cpp\/language\/fold<\/a><br \/>\nund da <a href=\"https:\/\/stackoverflow.com\/questions\/47216057\/how-to-write-a-fold-sum-function-for-c-tuple\">https:\/\/stackoverflow.com\/questions\/47216057\/how-to-write-a-fold-sum-function-for-c-tuple<\/a><\/p>\n<p>parameter pack zu std::tuple ist einfach<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\ntemplate&lt;typename...Ts&gt;\r\nauto func(const Ts&amp;...args) {\r\n    return std::tuple(args...);\r\n}\r\n\r\nauto func2() {\r\n    return func(1, 2.0, &quot;test&quot;);\r\n}\r\n<\/pre>\n<p>https:\/\/stackoverflow.com\/questions\/47216057\/how-to-write-a-fold-sum-function-for-c-tuple<\/p>\n<p>Der template Type Ts besteht aus den drei einzelnen Typen int, double und const char*. Die Variable args... h\u00e4lt entsprechend die drei Werte. Das sieht man an den drei Punkten \"...\" bei der Type und Funktions Argument Definition. Die sagen aus, dass hier noch mehr kommt. Die drei Punkte beim erstellen vom tuple packen den parameter pack aus. Sinngem\u00e4\u00df wird der Ausdruck umgewandelt zu<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nreturn std::tuple&lt;int,double,const char&gt;{arg1, arg2, arg3};\r\n<\/pre>\n<p>Andersherum, also vom tuple zum parameter pack ist nicht so einfach. Ein Weg f\u00fchrt \u00fcber std::integer_sequence wie ich es im anderen Post gezeigt habe. Aber das ist wieder so viel Template ged\u00f6ns und man braucht zwei Funktionen. Ein anderer Weg f\u00fchrt \u00fcber C++17 std::apply und fold, wie in dem stackoverflow Post gezeigt. Man ben\u00f6tigt zeitgleich aber eine Funktion, welche beim fold auf die Argumente angewandt werden kann. Das ganze bewegt sich weg von dem WIE etwas passiert, hin zu dem WAS passieren soll. Dem bin ich positiv gegen\u00fcbergestellt.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nauto t = std::make_tuple( 1, 2.0 );\r\nauto func = &#x5B;]( auto... v ){ return ( v + ... ); };\r\nauto sum = std::apply(func, t);\r\n<\/pre>\n<p>In std::apply steckt eine std::integer_sequence drin, welche aus dem tuple erstellt und der Funktion \u00fcbergeben wird. damit haben wir wieder ein parameter pack. Mittels lambda Funktion spart man sich auch wieder die Templates. Letztendlich m\u00fcssen wir mit dem parameter pack irgendetwas tun, also wird der plus operator mittels fold aufgerufen.<\/p>\n<p>Das ist schon eine ganz andere Art zu Programmieren, so ganz ohne explizite Schleifen. Aber ich finde es gut. Verhindert Fehler und der Compiler kann mehr tun.<br \/>\nZum Abschluss noch ein kurzer Spa\u00df. Was passiert, wenn man ein tuple in ein parameter pack umwandelt und das zur\u00fcck in ein tuple? Und wie sieht der Assembercode dazu aus? Probieren wir es aus!<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nauto func(const std::tuple&lt;int,double,const char*&gt;&amp; t) {\r\n    auto f = &#x5B;](const auto&amp;...v){ return std::tuple{v...}; };\r\n    return std::apply(f, t);   \r\n}\r\n<\/pre>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nfunc(std::tuple&lt;int, double, char const*&gt; const&amp;):\r\n  movq %rdi, %rax\r\n  movq (%rsi), %rdx\r\n  movq %rdx, (%rdi)\r\n  movsd 8(%rsi), %xmm0\r\n  movsd %xmm0, 8(%rdi)\r\n  movl 16(%rsi), %edx\r\n  movl %edx, 16(%rdi)\r\n  ret\r\n<\/pre>\n<p>Nun es passiert nichts weiter ;) Es gibt Sieben Assembler Instruktionen. Im Prinzip werden die Argumente nur kopiert. Jede Kopieraktion braucht zwei Instruktionen, da nicht von Speicher zu Speicher kopiert werden kann. Nur von Speicher zu Register und von Register zu Speicher. Die Argumente stehen im rsi Register. Wenn mich nicht alles t\u00e4uscht, wird erst der const char Pointer kopiert. Also ein quadword mit 64 Byte. Danach kommt das double, erkennt man am xmm0 Register. Und zuletzt das int mit einer movl Instruktion.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Part1: print std::array with std:integer_sequence Part2: convert tuple to parameter pack Part 3: print std::array with std::apply and fold Part 4: fold over std::tuple und erzeugten Assembler Code Part 5: fold over std::tuple of std::vector of Types ... Part 6: apply generic lambda to tuple Part 7: Play with std::tuple and std::apply Guckst du hier [&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-3508","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\/3508","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=3508"}],"version-history":[{"count":7,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/3508\/revisions"}],"predecessor-version":[{"id":4997,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/3508\/revisions\/4997"}],"wp:attachment":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3508"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3508"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3508"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}