{"id":4138,"date":"2019-02-22T18:55:13","date_gmt":"2019-02-22T17:55:13","guid":{"rendered":"http:\/\/roboblog.fatal-fury.de\/?p=4138"},"modified":"2019-10-18T10:20:11","modified_gmt":"2019-10-18T09:20:11","slug":"c-guns-rvalue-referenz-forwarding-referenz-universal-referenz-wtf","status":"publish","type":"post","link":"http:\/\/roboblog.fatal-fury.de\/?p=4138","title":{"rendered":"C++ Guns: rvalue referenz, forwarding referenz, universal referenz WTF?"},"content":{"rendered":"<p>Die gute Nachricht: Normale Menschen m\u00fcssen das alles nicht verstehen. Auch Anwendungs- Programmierer und library designer brauchen die Details nicht zu wissen. Ihr k\u00f6nnt meine Regeln durchlesen, daran halten und dann STOP.<br \/>\nDie Details sind f\u00fcr Leute, die sich einem 1.5h Vortrag \u00fcber && anh\u00f6ren k\u00f6nnen.<\/p>\n<p>Streng genommen wird der Begriff \"universal referenz\" nicht im C++ std benutzt. Dies ist ein Begriff von Scott Meyers, der ihn benutzt um die Ding begreiflich zu machen. Ich stimme mit ihm \u00fcberein und benutze in diesem Text nicht den Begriff \"forwared referenz\" sondern \"universal referenz\". Viele sagen C++ sei so schon kompliziert genug. Man muss es ja nicht noch schlimmer machen. Weiterhin werde ich Abk\u00fcrzungen benutzen. rvalue referenz Rref. universal referenz Uref.<\/p>\n<p>Nun, Rref und Uref tauchen (auch) bei ownership transfer auf. Das ist IMO die einzige Stelle bei der man das braucht. Beispiele hierzu in <a href=\"http:\/\/roboblog.fatal-fury.de\/?p=4141\">C+ Guns: ACPL ownership transfer<\/a>.<br \/>\nNun sehen sich Rref und Uref von der Syntax her ziemlich gleich. Beide haben einen Typ und dann das doppele Kaufmanns-Und, Et-Zeichen &&. Nicht zu verwechseln mit dem logischen AND Operator. Aber f\u00fcr diesen nutzt ihr selbstverst\u00e4ndlich <em>and<\/em> und nicht <em>&&<\/em>.<br \/>\nEs kommt nun auf den Typ an. Wird er vom Compiler hergeleitet (deduction) und ist es GENAU (im Sinne von EXACT) die Form <em>T&&<\/em>, dann ist es Uref, sonst Rref. Der Typ T ist ein Template Parameter und sein Name nat\u00fcrlich frei w\u00e4hlbar. Aber sobald ein <em>const<\/em> hinzugef\u00fcgt wird, verschwindet das Uref und das Rref taucht auf.<\/p>\n<p>Im ersten Beispiel (in dem verlinkten Artikel) ist somit Rref am Werk. Im zweiten Beispiel Uref. Und im dritten garnichts, weil man von const Variablen nicht moven kann!<\/p>\n<p>Funktionen \u00fcberladen mit Rref und Uref ist so eine Sache. Uref ist eine <strong>_*UNIVERSAL*_!!!<\/strong> Referenz. Sie behandelt <strong>ALLES<\/strong>. Und damit ist exakt alles gemeint. Nun ist es technisch (Stand 02.2019 pre C++20) m\u00f6glich, eine Funktion zu \u00fcberladen, so dass die eine Rref und die andere Uref akzeptiert. Aber das macht keinen Sinn und ist meiner Meinung nach ein Compilezeit Fehler.<\/p>\n<p>Funktionen mit Rref und \"normalen\" Referenzen zu \u00fcberladen ist nat\u00fcrlich m\u00f6glich, gewollt und hilfreich. M\u00f6chte man mit den einen doch etwas anderes machen als mit den anderen (move vs. read only). Und da sich Rref und Uref \u00e4hnlich sehen, viel Spass!<\/p>\n<p>Jetzt wird aus jedem Rref und Uref wieder ein ganz normales lvalue. Weil die haben einen Variablennamen und eine Adresse. Zwangsl\u00e4ufig, sonst k\u00f6nnte man den Variablennamen beim programmieren ja nicht eintippen -_-<br \/>\nAlso muss wann immer eine Rref oder Uref Variable weiter benutzt wird, ein std::move oder std::forward kommen. F\u00fcr Rref, also move Operationen nutzen wir std::move. F\u00fcr Uref, also move oder copy Operationen nutzen wird std::forward. Benutzen wir keines von beiden, ist das meiner Meinung nach ein Compilezeit Fehler. Jemand sollte ein GCC PLugin schreiben.<\/p>\n<p>Regeln:<\/p>\n<li>Uref und Rref braucht man (unter anderem) f\u00fcr ownership transfer. Ihr werde es kaum brauchen.<\/li>\n<li>Uref genau wenn T ein template parameter und exact die Form T&&  vorliegt, ohne const \u00f6.\u00e4, sonst Rref.<\/li>\n<li>T&& verh\u00e4lt sich in der Praxis NICHT wie Rref. Es kommt auf T an.<\/li>\n<li>Wenn immer T&& im Code auftaucht: Gelber ALARM! Braucht man das wirklich? Wird \u00fcberall std::move() oder std::forward() angewandt?<\/li>\n<li>Von const Variablen kann man nicht moven.<\/li>\n<li>Funktionen \u00fcberladen mit Uref -> Fehler<\/li>\n<li>Rref und normale Referenzen \u00fcberladen -> Gut<\/li>\n<li>Rref -> std::move<\/li>\n<li>Uref -> std::forward<\/li>\n<li>Soll ownership tranfer UND eine Kopie m\u00f6glich sein, macht die Kopie explizit im Code deutlich:<\/li>\n<pre>\r\n \/\/ v ist KEINE uref, da kein template Parameter\r\nauto func(std::vector<int> && v) \r\n{ }\r\n\r\nstd::vector<int> v;\r\nfunc(acpl::moveOwnership(v)); \/\/ ownership transfer\r\nfunc(std::vector<int>(v)); \/\/ Kopie\r\n<\/pre>\n<p>STOP<\/p>\n<p>F\u00fcr weitere Informationen zu auto&&, decltype(x), decltype((x)) und sonstige Schmerzen schau euch den Vortrag von Scott Meyers an. Er ist wirklich gut!<br \/>\n<a href=\"https:\/\/channel9.msdn.com\/Shows\/Going+Deep\/Cpp-and-Beyond-2012-Scott-Meyers-Universal-References-in-Cpp11\">C++ and Beyond 2012: Scott Meyers - Universal References in C++11<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Die gute Nachricht: Normale Menschen m\u00fcssen das alles nicht verstehen. Auch Anwendungs- Programmierer und library designer brauchen die Details nicht zu wissen. Ihr k\u00f6nnt meine Regeln durchlesen, daran halten und dann STOP. Die Details sind f\u00fcr Leute, die sich einem 1.5h Vortrag \u00fcber &#038;& anh\u00f6ren k\u00f6nnen. Streng genommen wird der Begriff \"universal referenz\" nicht im [&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-4138","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\/4138","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=4138"}],"version-history":[{"count":14,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/4138\/revisions"}],"predecessor-version":[{"id":4552,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=\/wp\/v2\/posts\/4138\/revisions\/4552"}],"wp:attachment":[{"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4138"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4138"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/roboblog.fatal-fury.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4138"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}