{"id":392,"date":"2016-01-14T01:51:26","date_gmt":"2016-01-14T09:51:26","guid":{"rendered":"http:\/\/www.teamfizzgames.com\/Matt\/?p=392"},"modified":"2016-01-14T01:51:26","modified_gmt":"2016-01-14T09:51:26","slug":"enum-madness","status":"publish","type":"post","link":"https:\/\/www.teamfizzgames.com\/Matt\/enum-madness\/","title":{"rendered":"Enum Madness!"},"content":{"rendered":"<p>Last time I wrote a class for\u00a0a bitfield and a macro that allowed us to automatically size the bitfield storage based on size of flag set and platform storage sizes. \u00a0And that&#8217;s great and all, but we only went from something like Bitflag&lt;unsigned int&gt; m_flags to something like Bitflag&lt;BITFLAG_SIZE(28)&gt; m_flags. \u00a0It&#8217;s better from the perspective of what I was writing about in that last post, but you still have a hardcoded 28 sitting there, completely detached from the flag set it is trying to describe. \u00a0Wouldn&#8217;t it be great if you could feed your flag set directly into the BITFLAG_SIZE macro, and then changes to the flag set automatically change the macro, which changes the type? \u00a0Why, yes, yes it would.<\/p>\n<p>So, can we do it? \u00a0Absolutely! \u00a0But, before we get to that answer, we&#8217;re going to take a detour through enums.<\/p>\n<p>I love enums. \u00a0Especially unscoped enums wrapped inside of their own namespaces. \u00a0I use them all the time. \u00a0Most of that usage is to describe entries in a statically sized array, along the lines of this:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nnamespace CommandListLayers\r\n{\r\n  enum Layer\r\n  {\r\n    Read,\r\n    Pivot,\r\n    Write,\r\n    NumberOf\r\n  };\r\n}\r\n<\/pre>\n<p>I have a system that uses an array of 3 command lists to move render data between the game thread and the render thread; the read layer, the write layer, and the pivot layer. \u00a0I can initialize\u00a0the array with CommandListLayers::NumberOf, and any code I write can deal with each of the layers via the associated enumerator. \u00a0It&#8217;s clean and it&#8217;s easy. \u00a0I really like the NumberOf trick, but it&#8217;s also kind of tedious to always insert it at the end. \u00a0Or, being the stupid human that I am, maybe I forget to do it. \u00a0Who knows! \u00a0So, one day I came up with this dumb macro.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#define ARRAY_ENUM_BUILDER(name1, name2, ...) \\\r\n  namespace name1 { \\\r\n    enum name2 { \\\r\n      __VA_ARGS__, \\\r\n      NumberOf \\\r\n    }; \\\r\n  }\r\n<\/pre>\n<p>And that allows the enum declaration to look like this.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nARRAY_ENUM_BUILDER(\r\n  CommandListLayers, Layer, \r\n  Read,\r\n  Pivot,\r\n  Write\r\n)\r\n<\/pre>\n<p>So, I declared the namespace and enum name, all enumerator entries, and the NumberOf gets tacked onto the end with the correct value. \u00a0Great! \u00a0So, what does this have to do with my Bitflag class and the BITFLAG_SIZE macro? \u00a0Well, given the enum stuff I was already doing in my code, the next logical step was to do something like this.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nnamespace ProcessToggleFlags\r\n{\r\n  enum Flags\r\n  {\r\n    Lighting = (1 &lt;&lt; 0),\r\n    DepthOfField = (1 &lt;&lt; 1),\r\n    Wireframe = (1 &lt;&lt; 2),\r\n    DebugLines = (1 &lt;&lt; 3),\r\n    DebugText = (1 &lt;&lt; 4),\r\n    NumberOf = 5\r\n  };\r\n}\r\n<\/pre>\n<p>So, this is a little less great. \u00a0I have to manually assign a value to NumberOf since it would otherwise take the next integral value beyond (1 &lt;&lt; 4), which isn&#8217;t 5, which is what I would want NumberOf to be in this case. \u00a0So, the macro as it exists for building enums that describe arrays isn&#8217;t going to cut it. \u00a0That&#8217;s where this template code comes in!<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nnamespace enum_helpers\r\n{\r\n  template &lt;unsigned long long T&gt;\r\n  struct enum_size\r\n  {\r\n    static const unsigned long long count = enum_size&lt;(T &gt;&gt; 1)&gt;::count + 1;\r\n  };\r\n\r\n  template &lt;&gt;\r\n  struct enum_size&lt;0&gt;\r\n  {\r\n    static const unsigned long long count = 0;\r\n  };\r\n}\r\n<\/pre>\n<p>Using that template code, I can now create a new macro specifically to build enums for bitfields. \u00a0And that macro looks like this.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#define BITFLAG_ENUM_BUILDER(name1, name2, ...) \\\r\n  namespace name1 { \\\r\n    enum name2 : unsigned long long { \\\r\n      __VA_ARGS__, \\\r\n      Last, \\\r\n      NumberOf = enum_helpers::enum_size&lt;Last - 1&gt;::count \\\r\n    }; \\\r\n  }\r\n<\/pre>\n<p>Which allows my enum to becomes this.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nBITFLAG_ENUM_BUILDER(\r\n  ProcessToggleFlags, Flags, \r\n  Lighting = (1 &lt;&lt; 0),\r\n  DepthOfField = (1 &lt;&lt; 1),\r\n  Wireframe = (1 &lt;&lt; 2),\r\n  DebugLines = (1 &lt;&lt; 3),\r\n  DebugText = (1 &lt;&lt; 4)\r\n)\r\n<\/pre>\n<p>It works more or less the same as the ARRAY_ENUM_BUILDER macro, but it tacks on a Last entry with the sole purpose of being the parameter into the enum_size template, giving us the correct value for NumberOf when dealing with bit flags. \u00a0So, that&#8217;s great, right? \u00a0Now we can move from Bitflag&lt;BITFLAG_SIZE(28)&gt; m_flags to Bitflag&lt;BITFLAG_SIZE(ProcessToggleFlags::NumberOf)&gt; m_flags. \u00a0And that&#8217;s definitely better. \u00a0More or less where I want to be with this.<\/p>\n<p>However, there are still some things I&#8217;d like to improve. \u00a0It would be nice if I could get the element count from __VA_ARGS__ or iterate over the contents. \u00a0Then I could generate the type of the enum, insert the shift values, and any necessary suffixes on the 1&#8217;s from inside the macro. \u00a0And it isn&#8217;t like it&#8217;s completely undoable, but it moves into the realm of really gross macro code. \u00a0Code I will probably end up writing for myself, but it&#8217;s not overly scaleable so I didn&#8217;t want to include it here.<\/p>\n<p>But, that&#8217;s it. \u00a0This template and 2 macros make my life a lot easier. \u00a0Hopefully it will do the same for someone else. \u00a0Here is the download link if you want all of the source: <a href=\"http:\/\/www.teamfizzgames.com\/Matt\/download\/codesamples\/EnumHelpers.hpp\" target=\"_blank\">EnumHelpers.hpp<\/a>. \u00a0And if anyone has suggestions for improvements (especially for doing the things I mentioned in the previous paragraph!), I&#8217;d love to hear those.<\/p>\n<p>Until next time!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last time I wrote a class for\u00a0a bitfield and a macro that allowed us to automatically size the bitfield storage based on size of flag set and platform storage sizes. \u00a0And that&#8217;s great and all, but we only went from something like Bitflag&lt;unsigned int&gt; m_flags to something like Bitflag&lt;BITFLAG_SIZE(28)&gt; m_flags. \u2026 <a class=\"continue-reading-link\" href=\"https:\/\/www.teamfizzgames.com\/Matt\/enum-madness\/\"> Continue reading <span class=\"meta-nav\">&rarr; <\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[6],"tags":[29,28],"class_list":["post-392","post","type-post","status-publish","format-standard","hentry","category-nongraphicsdevelopment","tag-enums","tag-templates"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p39ImV-6k","_links":{"self":[{"href":"https:\/\/www.teamfizzgames.com\/Matt\/wp-json\/wp\/v2\/posts\/392","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.teamfizzgames.com\/Matt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.teamfizzgames.com\/Matt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.teamfizzgames.com\/Matt\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.teamfizzgames.com\/Matt\/wp-json\/wp\/v2\/comments?post=392"}],"version-history":[{"count":9,"href":"https:\/\/www.teamfizzgames.com\/Matt\/wp-json\/wp\/v2\/posts\/392\/revisions"}],"predecessor-version":[{"id":401,"href":"https:\/\/www.teamfizzgames.com\/Matt\/wp-json\/wp\/v2\/posts\/392\/revisions\/401"}],"wp:attachment":[{"href":"https:\/\/www.teamfizzgames.com\/Matt\/wp-json\/wp\/v2\/media?parent=392"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.teamfizzgames.com\/Matt\/wp-json\/wp\/v2\/categories?post=392"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.teamfizzgames.com\/Matt\/wp-json\/wp\/v2\/tags?post=392"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}