    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Empty Scoped Enums as Strong Aliases for Integral Types</title>
        <link>https://members.accu.org/index.php/articles/2683</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + Overload Journal #152 - August 2019</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c78/">Overload</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c401/">o152</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-401/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+401/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Empty Scoped Enums as Strong Aliases for Integral Types</h1>
<p><strong>Author:</strong>&nbsp;Bob Schmidt</p>
<p>
<strong>Date:</strong> 04 August 2019 19:36:52 +01:00 or Sun, 04 August 2019 19:36:52 +01:00</p>
<p><strong>Summary:</strong>&nbsp;Scoped enums have many advantages. Lukas BÃ¶ger demonstrates their use as strong types of numbers.</p>
<p><strong>Body:</strong>&nbsp;<p>Scoped enumerations were one of the easy-to-grasp C++11 features that quickly spread and became the intended, superior alternative to their unscoped siblings. Local enumerator scope and forward declarations reduce namespace pollution and compilation dependencies, while prohibited implicit conversions to integral types promote type safety.</p>

<pre class="programlisting">
  enum class Season {winter, spring, summer,
    autumn};

  Season s1 = Season::spring; // Ok


  // Error, no conversion to int:
  int s2 = Season::summer;
  // Error, must be Season::summer:
  Season s3 = summer;</pre>
  
<p>As with unscoped enums, it is possible to create an enumerator object from objects of its underlying type. In C++14, this is the way to go:</p>

<pre class="programlisting">
  auto s4 = Season(1);
  auto s5 = static_cast&lt;Season&gt;(2);</pre>
  
<p>Both versions are equivalent; an explicit type conversion on the right hand side (functional notation and cast expression) is used for copy initializing s4 and s5. The necessity to detour via copy initialization seems clumsy though, the <code>static_cast</code> version even looks like someone forced the compiler to perform a dubious conversion without warnings. Thanks to P0138 [<a href="#[Reis16]">Reis16</a>], C++17 mitigates this scenario by allowing for direct list initialization of scoped enums (braces mandatory, no narrowing conversions).</p>

<pre class="programlisting">
  Season s6{1};</pre>
  
<p>But why even try to construct an enumeration from a literal? Does such an initialization not defeat the whole purpose of an <code>enum</code>, i.e., accessing a set of constants via comprehensible names instead of magic numbers? This concern is justified, and <code>auto s = Season::spring</code> should indeed be the preferable way to initialize the above enumerator. But recall that enumerations without any explicit enumerator are valid, too, and then, there is no comprehensible name at hand. Empty scoped enumerations can be extraordinarily useful as strong type aliases for integral types, and the new list initialization adds the missing piece for their mainstream usage as such. But letâ€™s first cover some ground.</p>

<h2>What is a strong type alias and what problem does it solve?</h2>

<p>Type aliases in C++ (via the <code>typedef</code> or <code>using</code> keyword) introduce new type names, but not new types. They are <em>transparent</em>: various type aliases referring to the same underlying type can be interchanged without errors or even warnings.</p>

<pre class="programlisting">
  using InventoryId = int;
  using RoomNumber = int;
  
  void store(InventoryId what, RoomNumber where);
  
  // Ok, nothing but ints (bad!):
  store(RoomNumber{2}, InventoryId{10});</pre>
  
<p>Strengthening the restrictions on a type alias with respect to substitutability and computational base (its associated functionality) renders it a <em>strong type alias</em> or a <em>strong typedef</em>. This requires a distinct type and is used to enforce semantics at compile time and to improve the expressiveness of function parameters. Assuming a <code>StrongTypeDef</code> template at hand, the above example could be written as</p>

<pre class="programlisting">
  // Use a tag type as 2nd template parameter to
  // create unique types:
  using InventoryId = StrongTypeDef&lt;int, 
    struct InventoryIdTag&gt;;
  using RoomNumber = StrongTypeDef&lt;int, 
    struct RoomNumberTag&gt;;
  
  void store(InventoryId what, RoomNumber where);
  
  // Error, types don't match (good!):
  store(RoomNumber{2}, InventoryId{10});</pre>
  
<p>References to such techniques are numerous, see e.g. Matthew Wilsonâ€™s early outline and example implementation [<a href="#[Wilson03]">Wilson03</a>], Scott Meyerâ€™s  â€˜Make interfaces easy to use correctly and hard to use incorrectlyâ€™ in <em>Effective C++</em> [<a href="#[Meyers05]">Meyers05</a>] or Ben Deaneâ€™s talk â€˜Using Types Effectivelyâ€™ [<a href="#[Deane16]">Deane16</a>]. Exemplary implementations for internal purposes can be found in the Boost Serialization library [<a href="#[Ramey]">Ramey</a>], Llvm [<a href="#[Lattner04]">Lattner04</a>] or Chromium [<a href="#[Chromium]">Chromium</a>], while distinct libraries with strong type templates are e.g. type_safe [<a href="#[MÃ¼ller]">MÃ¼ller</a>] and Named Type [<a href="#[Boccara]">Boccara</a>].</p>

<h2>What is the design space of strong type aliases?</h2>

<p>The smallest and most restrictive set of operations is explicit construction from the underlying type and explicit conversion to it. The other extreme is a mirror of the complete computational base of the wrapped type (in case of an <code>int</code>, this includes bitshifting, modulo operators and so on). Most approaches are somewhere in the middle. Their design requires answers to the following questions.</p>

<ul>
	<li>Type safety and constructability: allow implicit conversions from or to the underlying type (both doesnâ€™t make any sense)? Provide a default constructor?</li>
	
	<li>Uniqueness upon reuse: create a new type by an additional tag type template parameter or wrap the strong typedef definition into a macro?</li>
	
	<li>Comparison and arithmetic operators: when wrapping types that support those, mirror a subset? When construction is explicit, should binary functions be duplicated for one parameter of the underlying type?</li>
	
	<li>Hashing, serialization, parsing: support insertion into <code>std::unordered_set</code>/<code>map</code>? Offer <code>operator&lt;&lt;</code> and/or <code>operator&gt;&gt;</code> for standard library streams? Support the upcoming fmt library?</li>
</ul>

<p>Finding agreeable answers for these questions is hard. An attempt to standardize â€˜Opaque Typedefsâ€™ as first-class C++ citizens could not succeed, see N3741 [<a href="#[Brown18]">Brown18</a>], and hence, when a strong typedef is needed, we must choose a library solution or ship our own â€“ except when the wrapped type is an integral one.</p>

<h2>How do empty scoped enumerators fit in?</h2>

<p>Letâ€™s clearly state that once again: scoped enumerators are restricted with respect to the wrapped type: it must be an integral type (<code>bool</code>, <code>int</code>, <code>unsigned short</code>, etc.). When a <code>double</code> or a <code>std::string</code> are involved, you are out of luck. But it turns out that integral types are the most commonly used ones; a quick-and-dirty regex scan of the Chromium sources showed that around half of all strong types wrap integral values. This is what the above example looks like with an empty enumeration:</p>

<pre class="programlisting">
  enum class InventoryId {};
  enum class RoomNumber {};
  
  void store(InventoryId what, RoomNumber where);
  
  // Error, types don't match (good!):
  store(RoomNumber{2}, InventoryId{10});</pre>
  
<p>Scoped enumerators must be explicitly constructed. Narrowing conversions during construction are invalid (which cannot even be enforced with a generic library type), default construction is allowed and yields zero or <code>false</code>. Retrieval of the underlying type requires a cast (functional, C-style or <code>static_cast</code>), so no laziness here. By default, the underlying type of a scoped enumeration is <code>int</code>, but this can be adjusted. Every definition creates a completely new type, but their definition is trivial â€“ this is a clean, built-in solution, requiring neither a macro nor an additional tag type. Objects of one type are totally ordered through the usual comparison operators, and std::hash works out of the box. Standard arithmetic or IO operations are not supported. Manually adding them as needed is straightforward, though admittedly, with many such enumerators, you will either end up polluting some namespace with greedy operator templates or go with a macro to not repeatedly implement the same functions for different types<a href="#FN01"><sup>1</sup></a>.</p>

<h2>So when am I supposed to use empty scoped enumerations?</h2>

<p>Every time a strong integral type seems handy for a function signature, an API, a vocabulary type in your project â€“ empty scoped enums should be your first consideration. These types are dead simple, they are as efficient as expressive and require no external dependency. C++17 makes them easy to instantiate, there is no burden left that keeps you from leveraging their strengths. Just keep that in mind for the next time you write an interface that uses integral parameters!</p>

<h2>References</h2>

<p class="bibliomixed"><a id="[Boccara]"></a>[Boccara] Jonathan Boccara <em>et al.</em>, Named Type, a header-only library for strong types. On GitHub at <a href="https://github.com/joboccara/NamedType/blob/master/named_type_impl.hpp">https://github.com/joboccara/NamedType/blob/master/named_type_impl.hpp</a></p>

<p class="bibliomixed"><a id="[Brown18]"></a>[Brown18] Walter Brown (2018) â€˜Toward Opaque Typedefs for C++1Yâ€™, v2 ISO/IEC JTC1/SC22/WG21 document N3741, 2018-08-30. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3741.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3741.pdf</a></p>

<p class="bibliomixed"><a id="[Chromium]"></a>[Chromium] Chromium Project, sources as retrieved in June 2019 from <a href="https://chromium.googlesource.com/chromium/src.git/+/refs/heads/master/base/util/type_safety/strong_alias.h">https://chromium.googlesource.com/chromium/src.git/+/refs/heads/master/base/util/type_safety/strong_alias.h</a></p>

<p class="bibliomixed"><a id="[Deane16]"></a>[Deane16] Ben Deane (2016) â€˜Using Types Effectivelyâ€™ from <em>CppCon 2016</em>, available at <a href="https://www.youtube.com/watch?v=ojZbFIQSdl8">https://www.youtube.com/watch?v=ojZbFIQSdl8</a></p>

<p class="bibliomixed"><a id="[Lattner04]"></a>[Lattner04] Chris Lattner and Vikram Adve (2004) â€˜Llvm: A Compilation Framework for Lifelong Program Analysis and Transformationâ€™ in <em>Proc. of the 2004 International Symposium on Code Generation and Optimization</em>, Palo Alto, California, 2004. The implementation on GitHub is available: <a href="https://github.com/llvm/llvm-project/blob/master/llvm/include/llvm/Support/YAMLTraits.h">https://github.com/llvm/llvm-project/blob/master/llvm/include/llvm/Support/YAMLTraits.h</a></p>

<p class="bibliomixed"><a id="[Meyers05]"></a>[Meyers05] Scott Meyers (2005) <em>Effective C++: 55 Specific Ways to Improve Your Programs and Designs</em>, 3rd. edition, Addison-Wesley.</p>

<p class="bibliomixed"><a id="[MÃ¼ller]"></a>[MÃ¼ller] Jonathan MÃ¼ller <em>et al.</em>, type_safe: Zero overhead utilities for preventing bugs at compile time. The implementation on GitHub is available: <a href="https://github.com/foonathan/type_safe/blob/master/include/type_safe/strong_typedef.hpp">https://github.com/foonathan/type_safe/blob/master/include/type_safe/strong_typedef.hpp</a></p>

<p class="bibliomixed"><a id="[Ramey]"></a>[Ramey] Robert Ramey <em>et al.</em>, Boost Serialization Library, Version 1.70. BOOST_STRONG_TYPEDEF (documentation) available at <a href="https://www.boost.org/doc/libs/1_70_0/libs/serialization/doc/strong_typedef.html">https://www.boost.org/doc/libs/1_70_0/libs/serialization/doc/strong_typedef.html</a></p>

<p class="bibliomixed"><a id="[Reis16]"></a>[Reis16] Gabriel Dos Reis, Construction Rules for enum class Valuesâ€™, ISO/IEC JTC1/SC22/WG21 document P0138, 2016-03-04. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0138r2.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0138r2.pdf</a></p>

<p class="bibliomixed"><a id="[Wilson03]"></a>[Wilson03] Matthew Wilson (2003) â€˜True typedefsâ€™ in <em>Dr. Dobbâ€™s Journal</em>, dated 01 March 2003. Available at: <a href="http://www.drdobbs.com/true-typedefs/184401633">http://www.drdobbs.com/true-typedefs/184401633</a></p>

<p class="footnote"></p>

<ul>
	<li><a id="FN01"></a>Strong type alias templates scale better here, as they provide operators through the Barton-Nackmann trick. This can get out of hand, though; ambitious solutions risk duplicating the Boost Operator Library.</li>
</ul>

<p class="bio"><b><span class="author">Lukas BÃ¶ger</span></b> is a civil engineer who stuck with Fortran77 during his PhD program and started a C++ side project to alleviate his frustration. This worked out, and he now develops power electronics simulation software for Plexim, ZÃ¼rich. He likes reading, brass music, Newton mechanics and his family..</p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
