{"id":5347,"date":"2017-11-17T18:34:06","date_gmt":"2017-11-17T18:34:06","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-for-unions\/"},"modified":"2023-06-26T12:01:53","modified_gmt":"2023-06-26T12:01:53","slug":"c-core-guidelines-rules-for-unions","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-for-unions\/","title":{"rendered":"C++ Core Guidelines: Rules for Unions"},"content":{"rendered":"<p>A union is a particular data type where all members start at the same address. A union can hold only one type at a time; therefore, you can save memory. A tagged union is a union that keeps track of its types.<\/p>\n<p><!--more--><\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5345\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/11\/Wolpertinger.png\" alt=\"Wolpertinger\" style=\"display: block; margin-left: auto; margin-right: auto;\" width=\"349\" height=\"394\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/11\/Wolpertinger.png 349w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/11\/Wolpertinger-266x300.png 266w\" sizes=\"auto, (max-width: 349px) 100vw, 349px\" \/><\/p>\n<p>Here are the four rules for unions.<\/p>\n<ul>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Ru-union\">C.180: Use <code class=\"highlighter-rouge no-highlight\">union<\/code>s to save memory<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Ru-naked\">C.181: Avoid \u201cnaked\u201d <code class=\"highlighter-rouge no-highlight\">union<\/code>s<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Ru-anonymous\">C.182: Use anonymous <code class=\"highlighter-rouge no-highlight\">union<\/code>s to implement tagged unions<\/a><\/li>\n<li><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Ru-pun\">C.183: Don\u2019t use a <code class=\"highlighter-rouge no-highlight\">union<\/code> for type punning<\/a><\/li>\n<\/ul>\n<p>Let&#8217;s start with the most obvious rule.<\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Ru-union\">C.180: Use <code class=\"highlighter-rouge no-highlight\">union<\/code>s to save memory<\/a><\/h2>\n<p>Because a union can hold only one type at one point at a time, you can save memory. The union will be as big as the biggest type.<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">union<\/span> Value {\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> i;\r\n    <span style=\"color: #007788; font-weight: bold;\">double<\/span> d;\r\n};\r\n\r\nValue v <span style=\"color: #555555;\">=<\/span> { <span style=\"color: #ff6600;\">123<\/span> };      <span style=\"color: #0099ff; font-style: italic;\">\/\/ now v holds an int<\/span>\r\ncout <span style=\"color: #555555;\">&lt;&lt;<\/span> v.i <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;    <span style=\"color: #0099ff; font-style: italic;\">\/\/ write 123<\/span>\r\nv.d <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">987.654<\/span>;          <span style=\"color: #0099ff; font-style: italic;\">\/\/ now v holds a double<\/span>\r\ncout <span style=\"color: #555555;\">&lt;&lt;<\/span> v.d <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;    <span style=\"color: #0099ff; font-style: italic;\">\/\/ write 987.654<\/span>\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p><span style=\"font-family: courier new,courier;\">Value<\/span> is a &#8220;naked&#8221; union. You should not use it according to the next rule.<\/p>\n<\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Ru-naked\">C.181: Avoid \u201cnaked\u201d <code class=\"highlighter-rouge no-highlight\">union<\/code>s<\/a><\/h2>\n<p>&#8220;Naked&#8221; unions are error-prone because you must keep track of the underlying type.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ nakedUnion.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;iostream&gt;<\/span>\r\n\r\n<span style=\"color: #006699; font-weight: bold;\">union<\/span> Value {\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> i;\r\n    <span style=\"color: #007788; font-weight: bold;\">double<\/span> d;\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n  \r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n  Value v;\r\n  v.d <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">987.654<\/span>;  <span style=\"color: #0099ff; font-style: italic;\">\/\/ v holds a double<\/span>\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"v.d: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> v.d <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;     \r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"v.i: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> v.i <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;      <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n  v.i <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">123<\/span>;     <span style=\"color: #0099ff; font-style: italic;\">\/\/ v holds an int<\/span>\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"v.i: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> v.i <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">\"v.d: \"<\/span> <span style=\"color: #555555;\">&lt;&lt;<\/span> v.d <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;      <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span>\r\n  \r\n  std<span style=\"color: #555555;\">::<\/span>cout <span style=\"color: #555555;\">&lt;&lt;<\/span> std<span style=\"color: #555555;\">::<\/span>endl;\r\n\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>&nbsp;The union holds a double in the first iteration and an int value in the second iteration. If you read a <span style=\"font-family: courier new,courier;\">double<\/span> as an <span style=\"font-family: courier new,courier;\">int<\/span> (1) or an <span style=\"font-family: courier new,courier;\">int<\/span> as a <span style=\"font-family: courier new,courier;\">double<\/span> (2), you get undefined behavior.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5346\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/11\/nakedUnion.png\" alt=\"nakedUnion\" width=\"300\" height=\"208\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/11\/nakedUnion.png 391w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2017\/11\/nakedUnion-300x208.png 300w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>&nbsp;To overcome this source of errors, you should use a tagged union.<\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Ru-anonymous\">C.182: Use anonymous <code class=\"highlighter-rouge no-highlight\">union<\/code>s to implement tagged unions<\/a><\/h2>\n<p>Implementing a tagged union is quite sophisticated. In case you are curious, have a look at rule <a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Ru-anonymous\">C.182<\/a>. I will just make it easy and will write about the new C++ standard.<\/p>\n<p>With C++17, we get a tagged union:<span style=\"font-family: courier new,courier;\"> std::variant<\/span>. <span style=\"font-family: courier new,courier;\">std::variant<\/span> is a type-safe union. Here is a first impression.<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #0099ff; font-style: italic;\">\/\/ variant.cpp<\/span>\r\n\r\n<span style=\"color: #009999;\">#include &lt;variant&gt;<\/span>\r\n<span style=\"color: #009999;\">#include &lt;string&gt;<\/span>\r\n \r\n<span style=\"color: #007788; font-weight: bold;\">int<\/span> <span style=\"color: #cc00ff;\">main<\/span>(){\r\n\r\n  std<span style=\"color: #555555;\">::<\/span>variant<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span>, <span style=\"color: #007788; font-weight: bold;\">float<\/span><span style=\"color: #555555;\">&gt;<\/span> v, w;       <span style=\"color: #0099ff; font-style: italic;\">\/\/ (1)<\/span>\r\n  v <span style=\"color: #555555;\">=<\/span> <span style=\"color: #ff6600;\">12<\/span>;                              <span style=\"color: #0099ff; font-style: italic;\">\/\/ v contains int<\/span>\r\n  <span style=\"color: #007788; font-weight: bold;\">int<\/span> i <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>get<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span>(v);            <span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)        <\/span>\r\n                                       \r\n  w <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>get<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&gt;<\/span>(v);                <span style=\"color: #0099ff; font-style: italic;\">\/\/ (3)<\/span>\r\n  w <span style=\"color: #555555;\">=<\/span> std<span style=\"color: #555555;\">::<\/span>get<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #ff6600;\">0<\/span><span style=\"color: #555555;\">&gt;<\/span>(v);                  <span style=\"color: #0099ff; font-style: italic;\">\/\/ same effect as the previous line<\/span>\r\n  w <span style=\"color: #555555;\">=<\/span> v;                               <span style=\"color: #0099ff; font-style: italic;\">\/\/ same effect as the previous line<\/span>\r\n\r\n                                       <span style=\"color: #0099ff; font-style: italic;\">\/\/ (4)<\/span>\r\n  <span style=\"color: #0099ff; font-style: italic;\">\/\/  std::get&lt;double&gt;(v);             \/\/ error: no double in [int, float]<\/span>\r\n  <span style=\"color: #0099ff; font-style: italic;\">\/\/  std::get&lt;3&gt;(v);                  \/\/ error: valid index values are 0 and 1<\/span>\r\n \r\n  try{\r\n    std<span style=\"color: #555555;\">::<\/span>get<span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">float<\/span><span style=\"color: #555555;\">&gt;<\/span>(w);                <span style=\"color: #0099ff; font-style: italic;\">\/\/ w contains int, not float: will throw<\/span>\r\n  }\r\n  <span style=\"color: #006699; font-weight: bold;\">catch<\/span> (std<span style=\"color: #555555;\">::<\/span>bad_variant_access<span style=\"color: #555555;\">&amp;<\/span>) {}\r\n \r\n                                       <span style=\"color: #0099ff; font-style: italic;\">\/\/ (5)<\/span>\r\n  std<span style=\"color: #555555;\">::<\/span>variant<span style=\"color: #555555;\">&lt;<\/span>std<span style=\"color: #555555;\">::<\/span>string<span style=\"color: #555555;\">&gt;<\/span> v(<span style=\"color: #cc3300;\">\"abc\"<\/span>);  <span style=\"color: #0099ff; font-style: italic;\">\/\/ converting constructors work when unambiguous<\/span>\r\n  v <span style=\"color: #555555;\">=<\/span> <span style=\"color: #cc3300;\">\"def\"<\/span>;                           <span style=\"color: #0099ff; font-style: italic;\">\/\/ converting assignment also works when unambiguous<\/span>\r\n\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>In (2), I define the two variants <span style=\"font-family: courier new,courier;\">v<\/span> and<span style=\"font-family: courier new,courier;\"> w<\/span>. Both can have an <span style=\"font-family: courier new,courier;\">int<\/span> and a <span style=\"font-family: courier new,courier;\">float<\/span> value. Their initial value is 0. This is the default value for the first underlying type. <span style=\"font-family: courier new,courier;\">v<\/span> becomes 12. <span style=\"font-family: courier new,courier;\">std::get&lt;int&gt;(v)<\/span> returns the value using the type. Line (3) and the following two lines show three possibilities to assign the variant <span style=\"font-family: courier new,courier;\">v<\/span> the variant <span style=\"font-family: courier new,courier;\">w.<\/span> But you have to keep a few rules in mind. You can ask for a variant&#8217;s value by type or index. The type must be unique and the index valid (4). If not, you will get a <span style=\"font-family: courier new,courier;\">std::bad_variant_access<\/span> exception. <span style=\"font-family: courier new,courier;\"><\/span>If the constructor or assignment call is unambiguous, a conversion occurs. This is why it&#8217;s possible to construct a <span style=\"font-family: courier new,courier;\">std::variant&lt;std::string&gt;<\/span> with a C-string or assign a new C-string to the variant (5).<\/p>\n<h2><a href=\"http:\/\/isocpp.github.io\/CppCoreGuidelines\/CppCoreGuidelines#Ru-pun\">C.183: Don\u2019t use a <code class=\"highlighter-rouge no-highlight\">union<\/code> for type punning<\/a><\/h2>\n<p>At first, what is type punning? Type punning is the possibility of a programming language intentionally subverting the type system to treat a type as a different type. One typical way to do type punning in C++ is to read the member of a union with a different type from the one with which it was written.<\/p>\n<p>What is wrong with the following function <span style=\"font-family: courier new,courier;\">bad?<\/span><\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #f0f3f3; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #006699; font-weight: bold;\">union<\/span> Pun {\r\n    <span style=\"color: #007788; font-weight: bold;\">int<\/span> x;\r\n    <span style=\"color: #007788; font-weight: bold;\">unsigned<\/span> <span style=\"color: #007788; font-weight: bold;\">char<\/span> c[<span style=\"color: #006699; font-weight: bold;\">sizeof<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span>)];\r\n};\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">bad<\/span>(Pun<span style=\"color: #555555;\">&amp;<\/span> u)\r\n{\r\n    u.x <span style=\"color: #555555;\">=<\/span> <span style=\"color: #cc3300;\">'x'<\/span>;\r\n    cout <span style=\"color: #555555;\">&lt;&lt;<\/span> u.c[<span style=\"color: #ff6600;\">0<\/span>] <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;       <span style=\"color: #0099ff; font-style: italic;\">\/\/ undefined behavior (1)<\/span>\r\n}\r\n\r\n<span style=\"color: #007788; font-weight: bold;\">void<\/span> <span style=\"color: #cc00ff;\">if_you_must_pun<\/span>(<span style=\"color: #007788; font-weight: bold;\">int<\/span><span style=\"color: #555555;\">&amp;<\/span> x)\r\n{\r\n    <span style=\"color: #006699; font-weight: bold;\">auto<\/span> p <span style=\"color: #555555;\">=<\/span> <span style=\"color: #006699; font-weight: bold;\">reinterpret_cast<\/span><span style=\"color: #555555;\">&lt;<\/span><span style=\"color: #007788; font-weight: bold;\">unsigned<\/span> <span style=\"color: #007788; font-weight: bold;\">char<\/span><span style=\"color: #555555;\">*&gt;<\/span>(<span style=\"color: #555555;\">&amp;<\/span>x);   <span style=\"color: #3366ff;\"><\/span><span style=\"color: #0099ff; font-style: italic;\">\/\/ (2)<\/span><\/pre>\n<pre style=\"margin: 0px; line-height: 125%;\"><span style=\"color: #3366ff;\"><\/span>    cout <span style=\"color: #555555;\">&lt;&lt;<\/span> p[<span style=\"color: #ff6600;\">0<\/span>] <span style=\"color: #555555;\">&lt;&lt;<\/span> <span style=\"color: #cc3300;\">'\\n'<\/span>;                            <span style=\"color: #0099ff; font-style: italic;\">\/\/ OK; better<\/span> <br \/>    <span style=\"color: #0099ff; font-style: italic;\">\/\/ ...<\/span> <br \/>}<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>Expression (1) has two issues. First and foremost, it&#8217;s undefined behavior. Second, the type punning is quite challenging to find. If you have to use type punning, do it with an explicit cast such as <span style=\"font-family: courier new,courier;\">reinterpret_cast <\/span>in (2). With <span style=\"font-family: courier new,courier;\">reinterpret_cast<\/span> you have at least the possibility to spot your type punning afterwards.<\/p>\n<h2>What&#8217;s next?<\/h2>\n<p>Admittedly, this final post on rules for classes and class hierarchies was a bit short. with the <a href=\"https:\/\/www.modernescpp.com\/index.php\/c-core-guidelines-rules-for-enumerations\">next post<\/a>, I will write about the next significant section: enumerations.<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A union is a particular data type where all members start at the same address. A union can hold only one type at a time; therefore, you can save memory. A tagged union is a union that keeps track of its types.<\/p>\n","protected":false},"author":21,"featured_media":5345,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[372],"tags":[499,500],"class_list":["post-5347","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-modern-c","tag-classes","tag-union"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5347","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=5347"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5347\/revisions"}],"predecessor-version":[{"id":6851,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5347\/revisions\/6851"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5345"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5347"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5347"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5347"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}