
{"id":4882,"date":"2023-09-05T10:24:22","date_gmt":"2023-09-05T14:24:22","guid":{"rendered":"https:\/\/ikriv.com\/blog\/?p=4882"},"modified":"2023-09-05T10:26:46","modified_gmt":"2023-09-05T14:26:46","slug":"c-stdoptional-and-stdvariant-will-copy-values-by-default","status":"publish","type":"post","link":"https:\/\/ikriv.com\/blog\/?p=4882","title":{"rendered":"C++: std::optional and std::variant will copy values by default"},"content":{"rendered":"<p><code>std::optional<\/code> and <code>std::variant<\/code> are attractive alternatives to raw pointers and unions, but they come with a caveat: when you create an optional\/variant from a &#8220;real&#8221; value, a copy will be created. To avoid that, one must use <code>reference_wrapper<\/code>, and of course be careful not to end up with a dangling reference.<\/p>\n<p>The following code demonstrates that copying occurs when a value is passed to a function accepting a variant:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#include &lt;iostream&gt;\r\n#include &lt;variant&gt;\r\n\r\nusing namespace std;\r\n\r\nstruct Foo {\r\n    Foo() { cout &lt;&lt; &quot;Foo constructed&quot; &lt;&lt; endl; }\r\n    Foo(Foo const&amp; other) { cout &lt;&lt; &quot;Foo copied&quot; &lt;&lt; endl; }\r\n    ~Foo() { cout &lt;&lt; &quot;Foo destroyed&quot; &lt;&lt; endl; }\r\n};\r\n\r\nstruct Bar {\r\n    Bar() { cout &lt;&lt; &quot;Bar constructed&quot; &lt;&lt; endl; }\r\n    Bar(Bar const&amp; other) { cout &lt;&lt; &quot;Bar copied&quot; &lt;&lt; endl; }\r\n    ~Bar() { cout &lt;&lt; &quot;Bar destroyed&quot; &lt;&lt; endl; }\r\n};\r\n\r\nvoid f(variant&lt;Foo,Bar&gt; foobar) {\r\n    auto const* text = holds_alternative&lt;Foo&gt;(foobar) \r\n        ? &quot;Foo&quot; \r\n        : (holds_alternative&lt;Bar&gt;(foobar) \r\n            ? &quot;Bar&quot; \r\n            : &quot;unknown&quot;);\r\n    cout &lt;&lt; &quot;f(&quot; &lt;&lt; text &lt;&lt; &quot;)&quot; &lt;&lt; endl;\r\n}\r\n\r\nint main()\r\n{\r\n    f(Foo{});\r\n    f(Bar{});\r\n\r\n    return 0;\r\n}\r\n<\/pre>\n<p>Output:<\/p>\n<pre>\r\nFoo constructed\r\nFoo copied\r\nf(Foo)\r\nFoo destroyed\r\nFoo destroyed\r\nBar constructed\r\nBar copied\r\nf(Bar)\r\nBar destroyed\r\nBar destroyed\r\n<\/pre>\n<p>To avoid copying, one must use a <code>reference_wrapper<\/code>. Note that it is now impossible to pass a temporary:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#include &lt;iostream&gt;\r\n#include &lt;variant&gt;\r\n#include &lt;functional&gt;\r\n\r\nusing namespace std;\r\n\r\nstruct Foo {\r\n    Foo() { cout &lt;&lt; &quot;Foo constructed&quot; &lt;&lt; endl; }\r\n    Foo(Foo const&amp; other) { cout &lt;&lt; &quot;Foo copied&quot; &lt;&lt; endl; }\r\n    ~Foo() { cout &lt;&lt; &quot;Foo destroyed&quot; &lt;&lt; endl; }\r\n};\r\n\r\nstruct Bar {\r\n    Bar() { cout &lt;&lt; &quot;Bar constructed&quot; &lt;&lt; endl; }\r\n    Bar(Bar const&amp; other) { cout &lt;&lt; &quot;Bar copied&quot; &lt;&lt; endl; }\r\n    ~Bar() { cout &lt;&lt; &quot;Bar destroyed&quot; &lt;&lt; endl; }\r\n};\r\n\r\nvoid g(variant&lt;reference_wrapper&lt;const Foo&gt;,reference_wrapper&lt;const Bar&gt;&gt; foobar) {\r\n    auto const* text = holds_alternative&lt;reference_wrapper&lt;const Foo&gt;&gt;(foobar) \r\n        ? &quot;Foo&quot; \r\n        : (holds_alternative&lt;reference_wrapper&lt;const Bar&gt;&gt;(foobar) \r\n            ? &quot;Bar&quot; \r\n            : &quot;unknown&quot;);\r\n    cout &lt;&lt; &quot;g(&quot; &lt;&lt; text &lt;&lt; &quot;)&quot; &lt;&lt; endl;\r\n}\r\n\r\n\r\nint main()\r\n{\r\n    Foo foo;\r\n    Bar bar;\r\n    g(foo);\r\n    g(bar);\r\n    return 0;\r\n}\r\n<\/pre>\n<p>Output:<\/p>\n<pre>\r\nFoo constructed\r\nBar constructed\r\ng(Foo)\r\ng(Bar)\r\nBar destroyed\r\nFoo destroyed\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>std::optional and std::variant are attractive alternatives to raw pointers and unions, but they come with a caveat: when you create an optional\/variant from a &#8220;real&#8221; value, a copy will be <a href=\"https:\/\/ikriv.com\/blog\/?p=4882\" class=\"more-link\">[&hellip;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"Layout":"","footnotes":""},"categories":[7],"tags":[],"class_list":["entry","author-ikriv","post-4882","post","type-post","status-publish","format-standard","category-cpp"],"_links":{"self":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/4882","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4882"}],"version-history":[{"count":4,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/4882\/revisions"}],"predecessor-version":[{"id":4886,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/4882\/revisions\/4886"}],"wp:attachment":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4882"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4882"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4882"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}