Project site

This commit is contained in:
Anton Bachin 2020-10-19 09:11:42 +03:00
commit 5cfa84f1b8
28 changed files with 5154 additions and 0 deletions

343
ApiReference.html Normal file
View File

@ -0,0 +1,343 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>API reference - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/ApiReference.html" />
<meta name="description" content="Detailed description of the Better Enums API." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="api">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="index.html">Home</a>
<a href="tutorial/HelloWorld.html">Tutorial</a>
<a href="ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<h2>API reference</h2>
<p><a id="contents"></a><h3 class="contents">Contents</h3><ul class="contents"><li><a href="#Overview">Overview</a></li><li><a href="#RunningExample">Running example</a></li><li><a href="#HelperFunctionsAndTypes">Helper functions and types</a><ul><li><a href="#Typedef_enumerated">typedef _enumerated</a></li><li><a href="#Operator+">operator +</a></li><li><a href="#ConstructorEnum_enumerated">constructor Enum(_enumerated)</a></li><li><a href="#StructBetter_enumsoptional">struct better_enums::optional</a></li></ul></li><li><a href="#ValueCountAndIteration">Value count and iteration</a><ul><li><a href="#_size">_size</a></li><li><a href="#_size_constant">_size_constant</a></li><li><a href="#Typedef_value_iterable">typedef _value_iterable</a></li><li><a href="#Typedef_value_iterator">typedef _value_iterator</a></li><li><a href="#_values">_values</a></li></ul></li><li><a href="#StringConversionAndIteration">String conversion and iteration</a><ul><li><a href="#_to_string">_to_string</a></li><li><a href="#_from_string">_from_string</a></li><li><a href="#_from_string_nothrow">_from_string_nothrow</a></li><li><a href="#_from_string_nocase">_from_string_nocase</a></li><li><a href="#_from_string_nocase_nothrow">_from_string_nocase_nothrow</a></li><li><a href="#_is_validconstChar*">_is_valid(const char*)</a></li><li><a href="#_is_valid_nocase">_is_valid_nocase</a></li><li><a href="#_name">_name</a></li><li><a href="#Typedef_name_iterable">typedef _name_iterable</a></li><li><a href="#Typedef_name_iterator">typedef _name_iterator</a></li><li><a href="#_names">_names</a></li></ul></li><li><a href="#IntegerConversion">Integer conversion</a><ul><li><a href="#Typedef_integral">typedef _integral</a></li><li><a href="#_to_integral">_to_integral</a></li><li><a href="#_from_integral">_from_integral</a></li><li><a href="#_from_integral_nothrow">_from_integral_nothrow</a></li><li><a href="#_from_integral_unchecked">_from_integral_unchecked</a></li><li><a href="#_is_valid_integral">_is_valid(_integral)</a></li></ul></li><li><a href="#IndexLookup">Index lookup</a><ul><li><a href="#_to_index">_to_index</a></li><li><a href="#_from_index">_from_index</a></li><li><a href="#_from_index_unchecked">_from_index_unchecked</a></li><li><a href="#_from_index_nothrow">_from_index_nothrow</a></li></ul></li><li><a href="#StreamOperators">Stream operators</a><ul><li><a href="#Operator&lt;&lt;">operator &lt;&lt;</a></li><li><a href="#Operator&gt;&gt;">operator &gt;&gt;</a></li></ul></li><li><a href="#Hashing">Hashing</a><ul><li><a href="#Better_enums_declare_std_hash">BETTER_ENUMS_DECLARE_STD_HASH</a></li></ul></li></ul></p>
<a id="Overview"></a><h3>Overview</h3>
<p>The declaration</p>
<pre>#include &lt;enum.h&gt;
<em>BETTER_ENUM</em>(<em>Enum</em>, <em>underlying_type</em>, <em>A</em>, <em>B</em>, <em>C</em>, ...)</pre><p>generates a new class type <code>Enum</code> which is notionally similar to the type
created by this <span class="cpp">C++</span><span class="eleven">11</span> declaration:</p>
<pre class="comment"><em>enum class Enum</em> : <em>underlying_type</em> {<em>A</em>, <em>B</em>, <em>C</em>, ...};</pre><p>That is, <code>Enum</code> is a scoped enumerated type with constants <code>Enum::A</code>, <code>Enum::B</code>,
<code>Enum::C</code>, and so on, with memory representation the same as <code>underlying_type</code>.
It is possible to supply initializers for any of the constants:</p>
<pre><em>BETTER_ENUM</em>(Enum, underlying_type, <em>A</em> = <em>1</em>, <em>B</em> = <em>constant_expression</em>, <em>C</em> = <em>A</em>, ...)</pre><p>The initializers have the same meaning and constraints as in a built-in <code>enum</code>
or <code>enum class</code> declaration.</p>
<hr>
<p>The principal differences between the types declared by the <code>BETTER_ENUM</code> macro
and <code>enum class</code> are:</p>
<ul>
<li><code>BETTER_ENUM</code> is available for <span class="cpp">C++</span><span class="eleven">98</span>
<a href="CompilerSupport.html">compilers</a> supporting <code>__VA_ARGS__</code> &mdash;
all major compilers &mdash; while <code>enum class</code> is restricted to <span class="cpp">C++</span><span class="eleven">11</span>,</li>
<li>the <code>BETTER_ENUM</code> type is implicitly convertible to integral types, though
this can be <a href="OptInFeatures.html#StrictConversions">disabled</a> when
using <span class="cpp">C++</span><span class="eleven">11</span>, and</li>
<li>the <code>BETTER_ENUM</code> type supports a set of reflective operations, detailed in
the rest of this reference.</li>
</ul>
<hr>
<p>The types produced by the <code>BETTER_ENUM</code> macro are called <em>Better Enums</em> in the
rest of this reference.</p>
<p>Better Enums are similar to their underlying type for the purposes of argument
passing. This means that they typically fit into a machine word, and should be
passed by value.</p>
<p>All names declared in the scope of a Better Enum are prefixed with an underscore
in order to avoid conflicts with potential constant names.</p>
<a id="RunningExample"></a><h3>Running example</h3>
<p>The rest of this reference uses the following declaration as a running example:</p>
<pre><em>BETTER_ENUM</em>(<em>Enum</em>, <em>int</em>, <em>A</em>, <em>B</em>, <em>C</em>)</pre><a id="HelperFunctionsAndTypes"></a><h3>Helper functions and types</h3>
<p>The types and functions described here make it possible to use Better Enums with
the rest of <span class="cpp">C++</span> in a reasonable fashion, or else they are referenced in the
rest of the documentation.</p>
<a id="Typedef_enumerated"></a><h4><em>typedef _enumerated</em></h4>
<p>An internal type used to declare constants. The <code>BETTER_ENUM</code> macro generates
something similar to</p>
<pre class="comment"><em>struct Enum</em> {
<em>enum _enumerated</em> : <em>int</em> {<em>A</em>, <em>B</em>, <em>C</em>};
// ...
};</pre><p>The user needs to be aware of <code>_enumerated</code> in only one situation. A literal
constant such as <code>Enum::A</code> is an expression of type <code>Enum::_enumerated</code>, not
<code>Enum</code>. It is not possible to directly call a method on the constant, as in
<code>Enum::A._to_string()</code>. This problem is addressed by operator <code>+</code>
<a href="#Operator+">below</a>.</p>
<a id="Operator+"></a><h4>non-member constexpr Enum unary <em>operator +</em>(_enumerated)</h4>
<p>Forces promotion of <a href="#Typedef_enumerated"><code>Enum::_enumerated</code></a> to <code>Enum</code>.
Provided to solve the problem described <a href="#Typedef_enumerated">above</a>. So:</p>
<pre>// Does not compile
<em>Enum::A</em>.<em>_to_string</em>()
// Compiles
(<em>+Enum::A</em>).<em>_to_string</em>()</pre><a id="ConstructorEnum_enumerated"></a><h4>constexpr implicit <em>constructor Enum(_enumerated)</em></h4>
<p>A constructor that performs implicit conversions of
<a href="#Typedef_enumerated"><code>Enum::_enumerated</code></a> to <code>Enum</code>. This allows code to use a
literal constant where <code>Enum</code> is expected, and the compiler can do an implicit
conversion. For example:</p>
<pre>void <em>do_something</em>(<em>Enum value</em>);
do_something(<em>+Enum::A</em>); // Not necessary
do_something(<em>Enum::A</em>); // Implicit conversion available
<em>Enum value</em> = <em>Enum::A</em>; // Implicit conversion</pre><p>The other constructors of <code>Enum</code> are the implicitly-generated copy and move
constructors. There is no default constructor. If you have comments on what a
default constructor should do, please <a href="Contact.html">let me know</a>.</p>
<a id="StructBetter_enumsoptional"></a><h4>non-member <em>struct better_enums::optional</em>&lt;Enum&gt;</h4>
<p>An optional <code>Enum</code> value. These are returned by the various <code>_nothrow</code>
functions, such as <a href="#_from_string_nothrow"><code>_from_string_nothrow</code></a>. This type is
meant to represent the possibility of failure. For example, suppose you have:</p>
<pre><em>better_enums::optional</em>&lt;<em>Enum</em>&gt; <em>maybe</em> = <em>_from_string_nothrow</em>(<em>"A"</em>);</pre><p>An optional value such as <code>maybe</code> is convertible to <code>bool</code>. If it converts to
<code>true</code>, it holds a valid <code>Enum</code> value. Otherwise, if it converts to <code>false</code>, the
operation that produced the optional value failed. So, you can continue with</p>
<pre><em>if</em> (<em>maybe</em>) {
// The string conversion succeeded
do_something(<em>*maybe</em>);
}
<em>else</em> {
// The string conversion failed
}</pre><p>As you can see, <code>*maybe</code> evaluates to the <code>Enum</code> value, in this case <code>Enum::A</code>.</p>
<p>The rest of this reference refers to this type as simply <code>optional</code>, as if you
had entered</p>
<pre class="comment">using <em>optional</em> = <em>better_enums::optional</em>&lt;<em>Enum</em>&gt;;</pre><a id="ValueCountAndIteration"></a><h3>Value count and iteration</h3>
<p>The types and members described here have to do with the sequence of constants
declared, i.e. <code>A</code>, <code>B</code>, <code>C</code> in the <a href="#RunningExample">running example</a>.</p>
<a id="_size"></a><h4>static constexpr size_t <em>_size</em>()</h4>
<p>The number of constants declared. <code>Enum::_size() == 3</code>.</p>
<a id="_size_constant"></a><h4>static constexpr const size_t <em>_size_constant</em></h4>
<p>Same as <a href="#_size"><code>_size</code></a>, but a constant instead of a function. This is
provided for use in <span class="cpp">C++</span><span class="eleven">98</span> constant expressions.</p>
<a id="Typedef_value_iterable"></a><h4><em>typedef _value_iterable</em></h4>
<p>Type of object that permits iteration over the constants. Has at least
<code>constexpr</code> <code>begin()</code>, <code>end()</code>, and <code>size()</code> methods, and <code>constexpr</code>
<code>operator[]</code>. Iteration visits each <em>declared</em> constant, even if multiple
constants have the same value, and visits them in order of declaration. See
usage examples under <a href="#_values"><code>_values</code></a>.</p>
<a id="Typedef_value_iterator"></a><h4><em>typedef _value_iterator</em></h4>
<p>Random-access iterator type for <a href="#_value_iterable"><code>_value_iterable</code></a>. Most
operations, including dereferencing, are <code>constexpr</code>. The exceptions are
mutating operators such as <code>operator++</code>. In <code>constexpr</code> code, that can be
replaced with addition of <code>1</code>. You typically don't have to refer to this type
directly.</p>
<a id="_values"></a><h4>static constexpr _value_iterable <em>_values</em>()</h4>
<p><code>constexpr</code> access to the sequence of declared constants. For example:</p>
<pre><em>for</em> (size_t index = 0; <em>index</em> &lt; <em>Enum::_values().size()</em>; ++index)
do_something(<em>Enum::_values()[index]</em>);</pre><p>or, using iterators:</p>
<pre><em>for</em> (Enum::_value_iterator iterator = <em>Enum::_values().begin()</em>;
iterator != <em>Enum::_values().end()</em>; ++iterator) {
do_something(<em>*iterator</em>);
}</pre><p>or, in <span class="cpp">C++</span><span class="eleven">11</span>:</p>
<pre><em>for</em> (Enum value : <em>Enum::_values()</em>)
do_something(<em>value</em>);</pre><a id="StringConversionAndIteration"></a><h3>String conversion and iteration</h3>
<a id="_to_string"></a><h4>member constexpr? const char* <em>_to_string</em>() const</h4>
<p>Returns the string representation a Better Enum value. For example:</p>
<pre>Enum value = <em>Enum::A</em>;
value.<em>_to_string</em>(); // Same as "A".</pre><p>If two or more constants have the same numeric value, it is undefined which name
<code>_to_string</code> will choose, but it will choose one of them.</p>
<p>If <code>value</code> is not equal to the representation of any declared constant, for
example if it was obtained using an unchecked conversion such as</p>
<pre>Enum value = <em>Enum::_from_integral_unchecked</em>(<em>0xbadc0de</em>);</pre><p>then the behavior of <code>value._to_string</code> is undefined.</p>
<p>Running time is linear in the number of declared constants.</p>
<p>This method is not <code>constexpr</code> by default. Read
<a href="OptInFeatures.html#CompileTimeNameTrimming">here</a> for information
about making it <code>constexpr</code>.</p>
<a id="_from_string"></a><h4>static constexpr Enum <em>_from_string</em>(const char*)</h4>
<p>If the given string is the exact name of a declared constant, returns the
constant. Otherwise, throws <code>std::runtime_error</code>. Running time is linear in the
number of declared constants multiplied by the length of the longest constant.</p>
<a id="_from_string_nothrow"></a><h4>static constexpr optional&lt;Enum&gt; <em>_from_string_nothrow</em>(const char*)</h4>
<p>Same as <a href="#_from_string"><code>_from_string</code></a>, but does not throw an exception on
failure. Returns an <a href="#StructBetter_enumsoptional">optional value</a> instead.</p>
<a id="_from_string_nocase"></a><h4>static constexpr Enum <em>_from_string_nocase</em>(const char*)</h4>
<p>Same as <a href="#_from_string"><code>_from_string</code></a>, but comparison is up to case, in the
usual sense in the Latin-1 encoding.</p>
<a id="_from_string_nocase_nothrow"></a><h4>static constexpr optional&lt;Enum&gt; <em>_from_string_nocase_nothrow</em>(const char*)</h4>
<p>Is to <a href="#_from_string_nocase"><code>_from_string_nocase</code></a> as
<a href="#_from_string_nothrow"><code>_from_string_nothrow</code></a> is to
<a href="#_from_string"><code>_from_string</code></a>.</p>
<a id="_is_validconstChar*"></a><h4>static constexpr bool <em>_is_valid(const char*)</em></h4>
<p>Evaluates to <code>true</code> if and only if the given string is the exact name of a
declared constant. Running time is the same as for
<a href="#_from_string"><code>_from_string</code></a>.</p>
<a id="_is_valid_nocase"></a><h4>static constexpr bool <em>_is_valid_nocase</em>(const char*)</h4>
<p>The same as <a href="#_is_validconstChar*"><code>_is_valid</code></a>, but comparison is done up to
case as in <a href="#_from_string_nocase"><code>_from_string_nocase</code></a>.</p>
<a id="_name"></a><h4>static constexpr const char* <em>_name</em>()</h4>
<p>Evaluates to the name of the Better Enum type. <code>Enum::_name()</code> is the same
string as <code>"Enum"</code>.</p>
<a id="Typedef_name_iterable"></a><h4><em>typedef _name_iterable</em></h4>
<p>Type of object that permits iteration over names of declared constants. Has at
least <code>constexpr</code> <code>begin()</code>, <code>end()</code>, and <code>size()</code> methods. <code>operator[]</code> is also
available, but is <code>constexpr</code> if and only if <a href="#_to_string"><code>_to_string</code></a> is
<code>constexpr</code>. Iteration visits constants in order of declaration. See usage
example under <a href="#_names"><code>_names</code></a>.</p>
<a id="Typedef_name_iterator"></a><h4><em>typedef _name_iterator</em></h4>
<p>Random-access iterator type for <code>_name_iterable</code>. Most operations are
<code>constexpr</code>, but dereferencing is <code>constexpr</code> if and only if
<a href="#_to_string"><code>_to_string</code></a> is <code>constexpr</code>. Mutating operators such as
<code>operator++</code> are not <code>constexpr</code> due to their nature &mdash; adding <code>1</code> is a
<code>constexpr</code> alternative. You typically don't have to refer to this type
directly.</p>
<a id="_names"></a><h4>static constexpr? _name_iterable <em>_names</em>()</h4>
<p>Access to the sequence of declared constant names. For example:</p>
<pre><em>for</em> (size_t index = 0; <em>index</em> &lt; <em>Enum::_names().size()</em>; ++index)
std::cout &lt;&lt; <em>Enum::_names()[index]</em> &lt;&lt; std::endl;</pre><p>or, using iterators:</p>
<pre><em>for</em> (Enum::_name_iterator iterator = <em>Enum::_names().begin()</em>;
iterator != <em>Enum::_names().end()</em>; ++iterator) {
std::cout &lt;&lt; <em>*iterator</em> &lt;&lt; std::endl;
}</pre><p>or, in <span class="cpp">C++</span><span class="eleven">11</span>:</p>
<pre><em>for</em> (const char *name : <em>Enum::_names()</em>)
std::cout &lt;&lt; <em>name</em> &lt;&lt; std::endl;</pre><p><code>constexpr</code> if and only if <a href="#_to_string"><code>_to_string</code></a> is <code>constexpr</code>.</p>
<a id="IntegerConversion"></a><h3>Integer conversion</h3>
<p>Better Enums are already represented as integers at run time. Values of the
<a href="#RunningExample">running example</a> type <code>Enum</code> are the same as <code>ints</code>. However,
<code>Enum</code> is a distinct type from <code>int</code> during type checking, the main difference
being that its range of valid values is restricted to only the ones you have
declared.</p>
<p>This section describes the various translations between <code>Enum</code> and <code>int</code> that
are available. Each one translates the type, but at run time, most are no-ops,
or validity checks followed by no-ops.</p>
<a id="Typedef_integral"></a><h4><em>typedef _integral</em></h4>
<p>The <em>underlying</em> or <em>representation</em> type of the Better Enum. For example,
<code>Enum::_integral</code> is the same type as <code>int</code>. Each Better Enum has the same size
and alignment requirement as its representation type.</p>
<a id="_to_integral"></a><h4>member constexpr _integral <em>_to_integral</em>() const</h4>
<p>No-op conversion of a Better Enum to a value of its representation type. For
example,</p>
<pre>(+<em>Enum::C</em>)<em>._to_integral</em>() == <em>2</em></pre><p>Note that Better Enums are already implicitly convertible to their underlying
integral types <a href="OptInFeatures.html#StrictConversions">by default</a>.
You may still want to use this function, however, for clarity, and to ensure
that your code remains compatible if the strict conversions feature is enabled
later.</p>
<a id="_from_integral"></a><h4>static constexpr Enum <em>_from_integral</em>(_integral)</h4>
<p>Checked conversion of an integer to a Better Enum value. The check runs in time
linear in the number of declared constants, but the conversion itself is a
no-op. Throws <code>std::runtime_error</code> if the given integer is not the numeric value
of one of the declared constants.</p>
<pre><em>Enum::_from_integral</em>(<em>2</em>); // Enum::C
<em>Enum::_from_integral</em>(<em>42</em>); // std::runtime_error</pre><a id="_from_integral_nothrow"></a><h4>static constexpr optional&lt;Enum&gt; <em>_from_integral_nothrow</em>(_integral)</h4>
<p>Checked conversion as <a href="#_from_integral"><code>_from_integral</code></a>, but does not throw an
exception on failure. Returns an <a href="#StructBetter_enumsoptional">optional value</a>
instead.</p>
<a id="_from_integral_unchecked"></a><h4>static constexpr Enum <em>_from_integral_unchecked</em>(_integral)</h4>
<p>No-op unchecked conversion of an integer to a Better Enum value. If the given
integer is not the numeric value of one of the declared constants, the behavior
of all subsequent operations on the Better Enum value is undefined.</p>
<p>This is the direct inverse of <a href="#_to_integral"><code>_to_integral</code></a>. Here are no-op
round trips between <code>int</code> and <code>Enum</code>:</p>
<pre><em>Enum::_from_integral_unchecked</em>(value.<em>_to_integral</em>());
<em>Enum::_from_integral_unchecked</em>(integer).<em>_to_integral</em>();</pre><p>You should not use this function on untrusted input, however.</p>
<a id="_is_valid_integral"></a><h4>static constexpr bool <em>_is_valid(_integral)</em></h4>
<p>Evaluates to <code>true</code> if and only if the given integer is the numeric value of one
of the declared constants. Running time is linear in the number of declared
constants.</p>
<a id="IndexLookup"></a><h3>Index lookup</h3>
<a id="_to_index"></a><h4>member constexpr std::size_t <em>_to_index</em>() const</h4>
<p>Returns the index of a Better Enum value within its enum declaration. The index
is determined from the value only; if two constants in the declaration have the
same value, this function may return the index of either constant.</p>
<p>If the value does not correspond to any constant in the declaration (for
example, if it was obtained using an unchecked conversion or a cast), then the
behavior of <code>value._to_index</code> is undefined.</p>
<a id="_from_index"></a><h4>static constexpr Enum <em>_from_index</em>(size_t)</h4>
<p>Returns the value of the constant with the given index. Throws
<code>std::runtime_error</code> if not given the index of one of the constants.</p>
<a id="_from_index_unchecked"></a><h4>static constexpr Enum <em>_from_index_unchecked</em>(size_t)</h4>
<p>Returns the value of the constant with the given index. If not given one of the
constants in the declaration of the enum, the returned value is undefined.</p>
<a id="_from_index_nothrow"></a><h4>static constexpr optional&lt;Enum&gt; <em>_from_index_nothrow</em>(size_t)</h4>
<p>Returns the value of the constant with the given index.</p>
<a id="StreamOperators"></a><h3>Stream operators</h3>
<a id="Operator&lt;&lt;"></a><h4>non-member std::ostream&amp; <em>operator &lt;&lt;</em>(std::ostream&amp;, const Enum&amp;)</h4>
<p>Formats the given enum to the given stream in the same way as
<a href="#_to_string"><code>_to_string</code></a>.</p>
<a id="Operator&gt;&gt;"></a><h4>non-member std::istream&amp; <em>operator &gt;&gt;</em>(std::istream&amp;, Enum&amp;)</h4>
<p>Reads from the given stream and attempts to parse an enum value in the same way
as <a href="#_from_string"><code>_from_string</code></a>. In case of failure, sets the stream's
<code>failbit</code>.</p>
<a id="Hashing"></a><h3>Hashing</h3>
<a id="Better_enums_declare_std_hash"></a><h4>macro <em>BETTER_ENUMS_DECLARE_STD_HASH</em>(Enum)</h4>
<p>Use this outside namespace scope to declare a specialization of <code>std::hash</code> for
the type <code>Enum</code>. For example:</p>
<pre>// This declaration might be inside a namespace.
<em>BETTER_ENUM</em>(<em>Channel</em>, int, Red, Green, Blue)
// Later, outside the namespace:
<em>BETTER_ENUMS_DECLARE_STD_HASH</em>(<em>Channel</em>)</pre>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

205
CompilerSupport.html Normal file
View File

@ -0,0 +1,205 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Compiler support - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/CompilerSupport.html" />
<meta name="description" content="Better Enums compiler support, compatibility, feature detection, and automated
testing." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="index.html">Home</a>
<a href="tutorial/HelloWorld.html">Tutorial</a>
<a href="ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<h2>Compiler support</h2>
<p>Better Enums aims to support all major compilers. It is known to work on:</p>
<ul>
<li>clang 3.3 to 3.9</li>
<li>gcc 4.3 to 5.3</li>
<li>Visual C++ 2008 to 2015.</li>
</ul>
<p>The library can be used with any compiler that supports either <span class="cpp">C++</span><span class="eleven">11</span>, or <span class="cpp">C++</span><span class="eleven">98</span>
with the <code>__VA_ARGS__</code> extension. This includes every version of gcc and clang I
have ever heard of, and Visual C++ down to 2005.</p>
<p>To ensure that nothing is broken, every release of Better Enums is
<a href="https://github.com/aantron/better-enums/tree/master/test">tested</a> in multiple configuratins on the compilers
listed above. Testing includes the code in the tutorials, the unit tests, and a
multiple translation unit linking test. The full list of tested compilers and
configurations is given at <a href="#TestedConfigurations">the end of this page</a>.</p>
<a id="CompileTimeReflectionConfigurations"></a><h3>Compile-time reflection configurations</h3>
<p>Read this section if:</p>
<ul>
<li>you want to use Better Enums reflection at compile time, and need to know
exactly what features are supported on your compiler, or</li>
<li>Better Enums is choosing the wrong configuration automatically and you need
to force a different choice.</li>
</ul>
<p>All features of Better Enums are always available for run-time use. However, for
compile-time use, Better Enums has two main configurations: <span class="cpp">C++</span><span class="eleven">98</span> mode and
<code>constexpr</code> mode. Better Enums tries to detect which compiler is compiling it
and select the appropriate mode.</p>
<p>For performance reasons, <code>constexpr</code> mode is subdivided into a "fast"
<code>constexpr</code> mode and an
<a href="OptInFeatures.html#CompileTimeNameTrimming">opt-in</a> "full" (slow)
<code>constexpr</code> mode. The three modes can be ranked, with each next mode including
all the features of the preceding ones:</p>
<ul>
<li><span class="cpp">C++</span><span class="eleven">98</span></li>
<li>fast <code>constexpr</code></li>
<li>full <code>constexpr</code></li>
</ul>
<p>Only <code>_size</code> is supported at compile time in <span class="cpp">C++</span><span class="eleven">98</span> mode. Fast <code>constexpr</code> mode
adds all other members besides <code>_to_string</code> and <code>_names</code>. Full <code>constexpr</code> mode
supports those at compile time as well.</p>
<hr>
<p>The mode selection code works as follows:</p>
<ul>
<li>First, as of the time of this writing, only clang and gcc support
<code>constexpr</code>. So, if you are using any other compiler, Better Enums is in
<span class="cpp">C++</span><span class="eleven">98</span> mode.</li>
<li>If you are using gcc 4.7 or higher or clang, Better Enums uses those
compilers' predefined macros to detect whether <code>constexpr</code> support is
enabled with compiler flags. If so, it is in one of the <code>constexpr</code> mode.
Otherwise, it falls back to <span class="cpp">C++</span><span class="eleven">98</span> mode.</li>
<li>The default <code>constexpr</code> mode is fast <code>constexpr</code>. If you want to enable
full <code>constexpr</code> mode for some or all of your enums, follow
<a href="OptInFeatures.html#CompileTimeNameTrimming">these</a> instructions.</li>
</ul>
<p>If Better Enums picks the wrong mode, you can force <code>constexpr</code> mode by defining
<code>BETTER_ENUMS_CONSTEXPR</code> before including <code>enum.h</code>, typically by passing an
option to your compiler, or you can force <span class="cpp">C++</span><span class="eleven">98</span> mode by defining
<code>BETTER_ENUMS_NO_CONSTEXPR</code>.</p>
<p>If you are using a compiler for which Better Enums makes the wrong choice,
please <a href="Contact.html">let me know</a>. I will fix it and you won't have to
define these macros anymore.</p>
<a id="TestedConfigurations"></a><h3>Tested configurations</h3>
<pre class="comment">vc2015 /EHsc
vc2015 /EHsc /DBETTER_ENUMS_STRICT_CONVERSION
vc2013 /EHsc
vc2013 /EHsc /DBETTER_ENUMS_STRICT_CONVERSION
vc2012 /EHsc
vc2010 /EHsc
vc2008 /EHsc
clang++39 -std=c++11
clang++39 -std=c++11 -DBETTER_ENUMS_STRICT_CONVERSION
clang++39 -std=c++11 -DBETTER_ENUMS_CONSTEXPR_TO_STRING
clang++39 -std=c++98
clang++38 -std=c++11
clang++38 -std=c++11 -DBETTER_ENUMS_STRICT_CONVERSION
clang++38 -std=c++11 -DBETTER_ENUMS_CONSTEXPR_TO_STRING
clang++38 -std=c++98
clang++37 -std=c++11
clang++37 -std=c++11 -DBETTER_ENUMS_STRICT_CONVERSION
clang++37 -std=c++11 -DBETTER_ENUMS_CONSTEXPR_TO_STRING
clang++37 -std=c++98
clang++36 -std=c++11
clang++36 -std=c++11 -DBETTER_ENUMS_STRICT_CONVERSION
clang++36 -std=c++11 -DBETTER_ENUMS_CONSTEXPR_TO_STRING
clang++36 -std=c++98
clang++35 -std=c++11
clang++35 -std=c++11 -DBETTER_ENUMS_STRICT_CONVERSION
clang++35 -std=c++11 -DBETTER_ENUMS_CONSTEXPR_TO_STRING
clang++35 -std=c++98
clang++34 -std=c++11
clang++34 -std=c++11 -DBETTER_ENUMS_STRICT_CONVERSION
clang++34 -std=c++11 -DBETTER_ENUMS_CONSTEXPR_TO_STRING
clang++34 -std=c++98
clang++33 -std=c++98
g++53 -std=c++11
g++53 -std=c++11 -DBETTER_ENUMS_STRICT_CONVERSION
g++53 -std=c++11 -DBETTER_ENUMS_CONSTEXPR_TO_STRING
g++53 -std=c++98
g++49 -std=c++11
g++49 -std=c++11 -DBETTER_ENUMS_STRICT_CONVERSION
g++49 -std=c++11 -DBETTER_ENUMS_CONSTEXPR_TO_STRING
g++49 -std=c++98
g++48 -std=c++11
g++48 -std=c++11 -DBETTER_ENUMS_STRICT_CONVERSION
g++48 -std=c++11 -DBETTER_ENUMS_CONSTEXPR_TO_STRING
g++48 -std=c++98
g++47 -std=c++11
g++47 -std=c++11 -DBETTER_ENUMS_STRICT_CONVERSION
g++47 -std=c++11 -DBETTER_ENUMS_CONSTEXPR_TO_STRING
g++47 -std=c++98
g++46 -std=c++98
g++45 -std=c++98
g++44 -std=c++98
g++43 -std=c++98</pre>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

103
Contact.html Normal file
View File

@ -0,0 +1,103 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Contact - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/Contact.html" />
<meta name="description" content="Contact information for Better Enums bugs, issues, support, and feedback." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="index.html">Home</a>
<a href="tutorial/HelloWorld.html">Tutorial</a>
<a href="ApiReference.html">Reference</a>
<a href="Contact.html">Contact</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<h2>Contact</h2>
<ul>
<li>Send me an email: <a href="mailto:antonbachin@yahoo.com">antonbachin@yahoo.com</a>.</li>
<li>Visit the <a href="https://github.com/aantron/better-enums">GitHub</a> project to open an issue or get a development
version.</li>
</ul>
<p>I'm happy to hear any feedback. If you have any trouble using the library or
parsing the documentation, please don't hesitate to let me know. I'd also be
interested to hear about your use case, if you are willing to share :)</p>
<p>And, if you find this library helpful, give it a star on GitHub to let me know
you use it :)</p>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

301
DesignDecisionsFAQ.html Normal file
View File

@ -0,0 +1,301 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Design decisions FAQ - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/DesignDecisionsFAQ.html" />
<meta name="description" content="Better Enums design decisions and tradeoffs." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="index.html">Home</a>
<a href="tutorial/HelloWorld.html">Tutorial</a>
<a href="ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<h2>Design decisions FAQ</h2>
<p><span class="self">Better Enums</span> pushes at the edges of what is possible in standard <span class="cpp">C++</span>, and I've had to
make some difficult decisions as a result. You can imagine the set of
potential reflective enum implementations as a space, with axes such as "concise
syntax," "uniform interface," "compilation speed," "run-time performance," and
so on. As is typical in engineering, the constraints are such that as you move
to extremes along one axis, you have to retreat along others &mdash; for
example, some desirable aspects of concise syntax conflict with having a uniform
interface, which is nonetheless good for teachability, and compile-time
performance is, in some ways, at odds with run-time performance.</p>
<p>So, there are many variations possible on <span class="self">Better Enums</span>, and, in fact, I have tried and
maintained a few. This page describes how I chose the one that is published.
The choices are debatable, but I am attempting to record the debate. Hopefully,
this will either convince you that I have made a good choice, or, if you
disagree, you will have a good starting point for discussion, or even for
implementing an alternative.</p>
<p>I am always looking for new arguments and approaches. If you have an idea,
comment, criticism, please do <a href="Contact.html">let me know</a>.</p>
<p><a id="contents"></a><h3 class="contents">Contents</h3><ul class="contents"><li><a href="#WhyDoEnumMembersHaveUnderscores">Why do enum members have underscores?</a></li><li><a href="#WhyDoesBetterEnumsUseAMacroAtAll">Why does Better Enums use a macro at all?</a></li><li><a href="#WhyIsItNotPossibleToDeclareABetterEnumInsideAClass">Why is it not possible to declare a Better Enum inside a class?</a></li><li><a href="#ShouldBetterEnumsProvideEnum"objects"OrTraitsTypes">Should Better Enums provide enum "objects" or traits types?</a></li><li><a href="#WhyDoesBetterEnumsUseLinearScansForLookup">Why does Better Enums use linear scans for lookup?</a></li><li><a href="#WhyNotUseIndicesForTheRepresentation">Why not use indices for the representation?</a></li></ul></p>
<a id="WhyDoEnumMembersHaveUnderscores"></a><h3>Why do enum members have underscores?</h3>
<p>Enum members such as <code>_to_string</code> occupy the same scope as the names of
constants declared by the user. I chose to prefix members with underscores to
lessen the chances of collision. For example, take <code>_valid</code>, and suppose it was
<code>valid</code> instead. That would make this enum impossible:</p>
<pre><em>BETTER_ENUM(Status, char, valid, invalid)</em></pre><p>because the constant <code>Status::valid</code> would clash with the member
<code>Status::valid</code>.</p>
<p>Of course, users could try to declare constants with underscores as well, but I
find it easier to ask users not to do that, rather than ask them to worry about
a potentially growing set of reserved names, which they wouldn't fully know even
for a single version of Better Enums, without frequently looking at the API
documentation.</p>
<p>Alternatives to this involve separating the namespaces occupied by members and
constants. I don't think increasing nesting is an option, since nobody wants to
write <code>Status::values::valid</code> or <code>Status::operations::valid</code>. I don't think
moving constants out of <code>Status</code> is a good idea, since scoped constants is a
feature of Better Enums, which is especially important for <span class="cpp">C++</span><span class="eleven">98</span> usage.</p>
<p>This leaves the possibility of moving the operations performed by the members
into traits types, i.e. something like <code>traits&lt;Status&gt;::valid</code>. That is an
interesting option, and it has <a href="#Traits">its own section</a>. I have tried it, but
the verbosity increase is much greater than the benefit of dropping underscores,
so I chose not to do it.</p>
<a id="WhyDoesBetterEnumsUseAMacroAtAll"></a><h3>Why does Better Enums use a macro at all?</h3>
<p>Better Enums needs to turn the names of declared constants into strings, and I
don't believe there is any way to do this in standard <span class="cpp">C++</span> except by using the
preprocessor's macro parameter stringization operator (<code>#</code>). So, at the top
level, Better Enums has to provide a macro. I am, however, trying to keep the
user-facing macros to a minimum; in particular there is only one.</p>
<p>I think that's the best that is possible. Furthermore, apart from the macro
itself, the declaration looks very similar to a <span class="cpp">C++</span><span class="eleven">11</span> <code>enum</code> declaration, with
an underlying type, comma-separated constant list, and the same support for
initializers as built-in enums. So, I am trying to keep even this one macro out
of the user's way. I wouldn't accept any change that involved turning the
declaration into a preprocessor sequence or tuple, i.e. something like</p>
<pre><em>BETTER_ENUM(Channel, int, (Red)(Green)((Blue)(5)))</em></pre><p>even if it promised extra capabilities.</p>
<p>Better Enums uses additional macros internally, for two main purposes: to do the
actual work of stringizing the declared constants and assembling them into
arrays, and to configure itself by detecting which compiler it is running on.</p>
<p>I am not a fan of gratuitous macros, but in these cases they are unavoidable,
and, indeed, I am grateful for the stringization operator.</p>
<p><a id="NoEnumInsideClass"></a></p>
<a id="WhyIsItNotPossibleToDeclareABetterEnumInsideAClass"></a><h3>Why is it not possible to declare a Better Enum inside a class?</h3>
<p>This is due to an interaction between linkage and <code>constexpr</code>.</p>
<ol>
<li><p>Better Enums is a header-only library that declares arrays with static
storage, such as the array of constant names for each declared enum. Such
arrays can be declared in namespace scope, in class scope, or in function
scope, but they also need to be defined somewhere.</p>
<p>If <code>BETTER_ENUM</code> is to be usable in both namespace and class scope, it
already can't assume that it can declare arrays in namespace scope, since if
<code>BETTER_ENUM</code> is used in a class, its entire expansion will be enclosed in
the declaration of that class.</p>
<p>That leaves class scope and function scope. If the arrays are declared in
class scope, there needs to be a separate definition of them in some
translation unit. This is too burdensome for the user, because the separate
definition would involve repetition of the constants in the macro parameter
list, creating exactly the type of maintenance problem that Better Enums is
trying to eliminate.</p>
<p>Function scope is the only viable option remaining after considering linkage
constraints. Each array can be wrapped in a static function, which has a
static local variable, which is initialized with the array. The functions can
be called to get references to the arrays.</p>
<p>However....</p>
</li>
<li><p>These arrays need to be accessible to <code>constexpr</code> code in <span class="cpp">C++</span><span class="eleven">11</span>, and
<code>constexpr</code> functions are not allowed to have static local variables.</p>
</li>
</ol>
<p>Ironically, this seems like one place where <span class="cpp">C++</span><span class="eleven">98</span> is more "flexible," but only
for the reason that compile-time usage of Better Enums is not supported in
<span class="cpp">C++</span><span class="eleven">98</span>.</p>
<p><a id="Traits"></a></p>
<a id="ShouldBetterEnumsProvideEnum"objects"OrTraitsTypes"></a><h3>Should Better Enums provide enum "objects" or traits types?</h3>
<p>A Better Enum value is an "object," whose memory representation is the same as
its underlying type. For example,</p>
<pre><em>BETTER_ENUM(Channel, int, Red, Green, Blue)</em></pre><p>expands to something like</p>
<pre><em>struct Channel {
enum _enumerated : int { Red, Green, Blue };
int _value;</em>
// Strings array, _to_string, _from_string, etc.
<em>};</em></pre><hr>
<p>There is an alternative interpretation, in which the Better Enums library
generates enum traits instead, i.e. the generated arrays and members sit
alongside built-in enums instead of wrapping them:</p>
<pre><em>BETTER_ENUM(Channel, int, Red, Green, Blue)</em></pre><p>generates</p>
<pre><em>enum class Channel : int { Red, Green, Blue };</em>
<em>template &lt;&gt;
struct ::better_enums::traits&lt;Channel&gt; {
using _enumerated = Channel;</em>
// Strings array, to_string, from_string, etc.
<em>};</em></pre><hr>
<p>There are a number of advantages to the traits approach.</p>
<ul>
<li>The underscore prefixes can be dropped from member names, since they no longer
share a namespace with user-declared constants.</li>
<li>The interface, at first glance, becomes more uniform, since now every member
is a static member of the traits type. Without traits, <code>_to_string</code> is a
non-static member, while <code>_from_string</code> is a static member.</li>
<li><code>Channel</code> is one of the language's own enum types, instead of some mystery
type provided by Better Enums. This may make it easier to understand. It also
eliminates the problem with different syntaxes for <code>switch</code> statements
described <a href="OptInFeatures.html#StrictConversions">here</a>.</li>
</ul>
<p>However, it also introduces some difficulties.</p>
<ul>
<li>The syntax is more verbose, since everything becomes a member of the traits
type. For example, instead of <code>Channel::_from_string()</code>, you get
<code>better_enums::traits&lt;Channel&gt;::from_string()</code>. The underscore may be
unpleasant, but so far I have preferred the underscore to boilerplate.</li>
<li><p>The uniform interface ends up getting wrapped behind functions anyway, for the
sake of type inference. For example, the "naked" <code>to_string</code> function is
called as <code>better_enums::traits&lt;Channel&gt;::to_string(channel)</code>, which is
redundant, because the compiler could infer the type parameter <code>Channel</code> if it
was the parameter of the function instead of the traits type. So, the obvious
thing is to define such a wrapper function, which can then be called as
<code>better_enums::to_string(channel)</code>. No such function can be easily defined for
<code>from_string</code> and other <code>from_*</code> functions, however, because the type
parameters can't be inferred from arguments. So, the signatures of <code>to_*</code> and
<code>from_*</code> functions again effectively diverge, negating this advantage of
traits. The closest I can get with wrappers is
<code>better_enums::from_string&lt;Channel&gt;</code>, which has the same signature only in the
formal sense, i.e. modulo the difference in type inference.</p>
<p>I actually think there is a way to infer the type parameter from the return
type, similar to how it is done <a href="demo/SpecialValues.html">here</a>, but that will not be suitable
for all contexts, and the user may be surprised by ambiguous resolution error
messages when it is not.</p>
</li>
<li>Scoped constants are lost for <span class="cpp">C++</span><span class="eleven">98</span> unless Better Enums again wraps them in a
generated type, though it will be more lightweight than a full Better Enum of
the non-traits approach.</li>
<li>Traits types must be specialized in either the same namespace scope they are
declared in, or in an enclosing scope. This makes it impossible to declare an
enum and specialize traits for it in a user's custom namespace.</li>
</ul>
<p>Despite the disadvantages listed just above, I consider the traits approach
interesting &mdash; it's a close call. There is an
<a href="https://github.com/aantron/better-enums/tree/traits">out-of-date branch</a> containing a traits version of Better Enums.
You can see some of the usage in its <a href="https://github.com/aantron/better-enums/tree/traits/samples">samples</a> directory. I may
update it from time to time, especially if there is interest.</p>
<a id="WhyDoesBetterEnumsUseLinearScansForLookup"></a><h3>Why does Better Enums use linear scans for lookup?</h3>
<p>It seems that Better Enums needs to use the same algorithms at compile time as
at run time, because I have not found a way (and doubt there is one) to
determine, during the execution of a <code>constexpr</code> function, whether it is
executing at compile time or at run time. So, whatever data structures I use to
accelerate lookup, I have to generate them at compile time, to be available as
early as possible.</p>
<p>I tried to generate various data structures at compile time, but so far,
generation has been too slow. The fastest algorithm so far, a compile-time merge
sort based on template parameter packs, took over 100ms to run on the constant
set of a large enum. I would have to run three of these per enum &mdash; for the
constants, for the names, and for the names with case-insensitive comparison.
This results in a 300ms slowdown per enum, which is not acceptable, given that
on my system the same compiler takes 370ms to process <code>iostream</code>, and less than
10ms to process an enum without acceleration data structures. Declaring five
large enums with accelerated lookup would take 1.5 seconds of compilation time.
This doesn't scale to large projects with many translation units.</p>
<p>I am continuing to look for faster algorithms or better approaches, so faster
lookup may be coming to Better Enums in the future.</p>
<p>So far, I have tried Boost.MPL sort, Eric Niebler's Meta sort, my own selection
sort based on <code>constexpr</code>, and an insertion and merge sort based on parameter
packs. I cannot use (Boost?).Hana sort, because that requires <span class="cpp">C++</span><span class="eleven">14</span>. I am also
considering various hash table-like data structures, and providing two sets of
interfaces for compile-time and run-time usage, which is something I would
really rather not have to do. The latter option would be worth considering,
however, if I measured a significant improvement in running time from better
data structures &mdash; something I haven't gotten to yet because there doesn't
seem to be a data structure to measure that is not disqualified by the speed of
generation.</p>
<a id="WhyNotUseIndicesForTheRepresentation"></a><h3>Why not use indices for the representation?</h3>
<p>Representing Better Enum values by their indices in the declaration list seems
like a tempting solution for the problem of having multiple constants with the
same numeric value. It also speeds up some operations. For example, if a Better
Enum is simply an index, then getting its string representation is simply
indexing an array, rather than some kind of data structure lookup.</p>
<pre>// Representations 0, 1, 2, 3 instead of 1, 2, 3, 1.
<em>BETTER_ENUM(Kind, int, A = 1, B, C, D = A)</em></pre><p>Choosing this approach has serious drawbacks.</p>
<ul>
<li>The data structure lookup has simply been moved to another place. It now takes
time to convert from a literal <code>Kind::D</code> to a Better Enum.</li>
<li>It is still impossible to disambiguate between the literals <code>Kind::D</code> and
<code>Kind::A</code> (1 and 1). Only the Better Enums objects of type <code>Kind</code> that
represent <code>D</code> and <code>A</code> are different from each other (0 and 3). This is not
only a technical problem, but is also quite unintuitive.</li>
<li>Treating a Better Enum represented by an index as untyped memory produces
surprising results. This makes Better Enums much less useful with functions
such as <code>fwrite</code>. Worse, Better Enums become sensitive to declaration order
even when initializers are given explicitly. Using indices for the
representation makes it difficult to maintain compatibility with external
protocols and file formats.</li>
</ul>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

148
ExtendingLimits.html Normal file
View File

@ -0,0 +1,148 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Extending limits - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/ExtendingLimits.html" />
<meta name="description" content="How to extend limits imposed by internal macros in Better Enums." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="index.html">Home</a>
<a href="tutorial/HelloWorld.html">Tutorial</a>
<a href="ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<h2>Extending limits</h2>
<p>The <code>BETTER_ENUM</code> macro makes heavy use of the preprocessor, and some of the
internal macros have size limits. There are two: on the number of constants you
can declare, and on the maximum length of a constant name under very specific
conditions. If you run into either one, you can extend the limit by following
the instructions on this page.</p>
<p>The second limit, on the maximum length of a constant name, applies only when
you are compiling an enum in
<a href="OptInFeatures.html#CompileTimeNameTrimming">"full" <code>constexpr</code></a> mode
<em>and</em> the constant has an initializer. Otherwise, your constants can have names
of arbitrary length.</p>
<p>The default limits are 64 constants in an enum and 23 characters for initialized
constants of full-<code>constexpr</code> enums. To extend:</p>
<ol>
<li>Pick your desired limits. I will use 512 constants and 63 characters as an
example. Add 1 to the number of characters to account for the null
terminator &mdash; our numbers are now 512 and 64.</li>
<li>Get <code>make_macros.py</code> from your copy of the full Better Enums distribution
or from <a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/script/make_macros.py" download>GitHub</a>.</li>
<li>You will run this script to generate a header file containing some
replacement macros for <code>enum.h</code> to use. Pick a name for this file and a
location somewhere in your include path. I will assume that this file is
<code>common/enum_macros.h</code> in your project.</li>
<li>Run <code>python make_macros.py 512 64 &gt; common/enum_macros.h</code>.</li>
<li><p>Define <code>BETTER_ENUMS_MACRO_FILE &lt;common/enum_macros.h&gt;</code> before including
<code>enum.h</code>. This is typically done by supplying extra flags to the compiler
on the command line:</p>
<ul>
<li>For g++ and clang++, <code>-DBETTER_ENUMS_MACRO_FILE='&lt;common/enum_macros.h&gt;'</code></li>
<li>For VC++, <code>\DBETTER_ENUMS_MACRO_FILE='&lt;common/enum_macros.h&gt;'</code></li>
<li>With CMake, you may need something like
<code>add_definitions(-DBETTER_ENUMS_MACRO_FILE="${CMAKE_SOURCE_DIR}/src/enum-macros.h")</code></li>
</ul>
<p>You can also create a new header file that defines this macro, and then
includes <code>enum.h</code>. Then, include your new file everywhere where you would
otherwise include <code>enum.h</code>:</p>
<pre class="comment"><em>#pragma once
#define BETTER_ENUMS_MACRO_FILE &lt;common/enum_macros.h&gt;
#include &lt;enum.h&gt;</em></pre></li>
<li><p>Enjoy the looser limits. Just watch out &mdash; increasing the second
number can really slow down compilation of full-<code>constexpr</code> enums.</p>
</li>
<li>You don't need <code>make_macros.py</code> anymore. It's not part of your build
process and you can delete it.</li>
</ol>
<hr>
<p>I am paying attention to feedback, so if more than a few users say that the
default limit of 64 constants is too low, I will increase it to simplify
everyone's command line. The current choice of 64 is basically an arbitrary
guess, loosely informed by the following two facts about macro parameter limits:</p>
<ul>
<li>The default limit in Boost.Preprocessor is 64. Though Better Enums does not
use Boost, I took this number as a guideline.</li>
<li>The next power of two, 128, is more than <a href="https://msdn.microsoft.com/en-us/library/ft39hh4x.aspx">the number Visual C++ supports</a>
(127).</li>
</ul>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

183
GeneralUnderlyingTypes.html Normal file
View File

@ -0,0 +1,183 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>General underlying types - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/GeneralUnderlyingTypes.html" />
<meta name="description" content=""Using Better Enums with non-integral underlying types."" />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/master/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="index.html">Home</a>
<a href="tutorial/HelloWorld.html">Tutorial</a>
<a href="ApiReference.html">Reference</a>
<a href="Contact.html">Contact</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.10.1</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/master/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<h2>General underlying types</h2>
<p>The underlying type of a Better Enum doesn't have to be an integral type. It can
be any literal type <code>T</code>, as long as you provide a <code>constexpr</code> two-way mapping
between <code>T</code> and an integral type of your choosing. It also works in <span class="cpp">C++</span><span class="eleven">98</span>,
though, of course, <code>T</code> doesn't have to be literal and the mapping doesn't have
to be <code>constexpr</code> &mdash; everything will be done by Better Enums at run time.</p>
<p>Doing this enables the following usage:</p>
<pre>// The type. A color triplet.
<em>struct html_color {
uint8_t r, g, b;
constexpr html_color(uint8_t _r, uint8_t g, uint8_t b) :
r(_r), g(_g), b(_b) { }
};</em>
// The enum.
<em>ENUM(Color, html_color,
darksalmon = 0xc47451, purplemimosa = 0x9e7bff, slimegreen = 0xbce954)</em>
// The usage.
<em>Color c = Color::darksalmon;
std::cout &lt;&lt; "Red component: " &lt;&lt; c-&gt;r &lt;&lt; std::endl;
switch (c) {
case Color::darksalmon: // ...
case Color::purplemimosa: // ...
case Color::slimegreen: // ...
}</em></pre><p>As you can see, you can have an enumerated set of any literal type, and safely
use the values in <code>switch</code>, with the compiler checking exhaustiveness. You can
also access the type's members using the <code>enum-&gt;underlying_member</code> syntax.</p>
<p>You do have to supply the mapping to an integral type, however. One option is:</p>
<pre>// The mapping. It just stuffs bits.
<em>template &lt;&gt;
struct ::better_enums::underlying_traits&lt;html_color&gt; {
using integral_representation = unsigned int;
constexpr static html_color from_integral(unsigned int i)
{ return html_color(i &gt;&gt; 16 &amp; 0xff, i &gt;&gt; 8 &amp; 0xff, i &amp; 0xff); }
constexpr static unsigned int to_integral(html_color c)
{ return (unsigned int)c.r &lt;&lt; 16 | (unsigned int)c.g &lt;&lt; 8 | c.b; }
};</em></pre><a id="UsingConstructorsInInitializers"></a><h3>Using constructors in initializers</h3>
<p>The declaration above used only numeric initializers. It is possible to use the
type's own constructors, provided the type has a <code>constexpr</code> conversion to your
chosen integral type:</p>
<pre>// The type.
<em>struct html_color {
uint8_t r, g, b;
constexpr html_color(uint8_t _r, uint8_t g, uint8_t b) :
r(_r), g(_g), b(_b) { }
</em>// This is new:<em>
constexpr operator unsigned int() const
{ return (unsigned int)r &lt;&lt; 16 | (unsigned int)g &lt;&lt; 8 | b; }
};</em>
// The enum.
<em>ENUM(Color, html_color,
darksalmon = 0xc47451, purplemimosa = 0x9e7bff, slimegreen = 0xbce954,
celeste = html_color(0x50, 0xeb, 0xec))</em></pre><p>This is not possible at all in <span class="cpp">C++</span><span class="eleven">98</span>, however.</p>
<a id="LettingTheCompilerEnumerateYourLiteralType"></a><h3>Letting the compiler enumerate your literal type</h3>
<p>You don't have to use initializers. For example, as long as your example type
<code>file_descriptor</code> knows how to deal with the values, you can have the compiler
generate them in sequence:</p>
<pre><em>ENUM(FD, file_descriptor, STDIN, STDOUT, STDERR, SomePipeYourDaemonHas, ...)</em></pre><p>SAMPLE</p>
<p>You can see the code "in action" in the <a href="https://github.com/aantron/better-enums/blob/master/test/cxxtest/underlying.h">test case</a>. Be aware that it's
not very "nice," because it uses conditional compilation to run under multiple
compilers. I haven't written a clean sample or documentation yet simply because
this feature is in a very early stage of development.</p>
<a id="Discussion"></a><h3>Discussion</h3>
<p>This feature is still semi-experimental, though I expect it to remain stable,
except perhaps that I will make it possible to infer the type
<code>integral_representation</code>.</p>
<p>Any opinions are welcome.</p>
<ul>
<li>The main reason Better Enums needs you to supply and explicit mapping is
because it can't just get the "bits" of objects of underlying type in
<code>constexpr</code> code. Both <code>reinterpret_cast</code> and union abuse seem to be forbidden
in <code>constexpr</code> functions.</li>
<li>There is currently no way to have two different integral representaitons for
the same underlying type in different enums. I don't think that's a major use
case at this point, however.</li>
</ul>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015 Anton Bachin. Released under the BSD 2-clause license.
See
<a href="https://github.com/aantron/better-enums/blob/master/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.10.1.
</div>
</footer>
</body>
</html>

165
OptInFeatures.html Normal file
View File

@ -0,0 +1,165 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Opt-in features - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/OptInFeatures.html" />
<meta name="description" content="Optional Better Enums features, disabled by default for
performance or compatibility reasons." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="index.html">Home</a>
<a href="tutorial/HelloWorld.html">Tutorial</a>
<a href="ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<h2>Opt-in features</h2>
<p>Better Enums has two opt-in features. They are both "good," but they either hurt
compilation time or break compatibility with <span class="cpp">C++</span><span class="eleven">98</span>, so they are disabled by
default. Read this page if you want to enable them.</p>
<p><a id="contents"></a><h3 class="contents">Contents</h3><ul class="contents"><li><a href="#DefaultConstructors">Default constructors</a></li><li><a href="#CompileTimeNameTrimming">Compile-time name trimming</a></li><li><a href="#StrictConversions">Strict conversions</a></li><li><a href="#InjectingTokens">Injecting tokens</a></li></ul></p>
<a id="DefaultConstructors"></a><h3>Default constructors</h3>
<p>Better Enums generate with inaccessible (private or deleted) default
constructors. This is meant to help control where in your program Better Enums
values are introduced, and thus ensure that only valid, properly initialized
enum values are ever created.</p>
<p>If you want Better Enums to have a default constructor, you can do something
like the following:</p>
<pre><em>#define</em> <em>BETTER_ENUMS_DEFAULT_CONSTRUCTOR</em>(<em>Enum</em>) \
<em>public</em>: \
<em>Enum()</em> = <em>default</em>;
<em>#include</em> &lt;<em>enum.h</em>&gt;</pre><p>You can put this in its own header file, and include that header file instead of
including <code>enum.h</code> directly.</p>
<a id="CompileTimeNameTrimming"></a><h3>Compile-time name trimming</h3>
<p>This makes <code>_to_string</code> and <code>_names</code> <code>constexpr</code>, i.e. "full" <code>constexpr</code> mode.
To enable this for all enums, define <code>BETTER_ENUMS_CONSTEXPR_TO_STRING</code> before
including <code>enum.h</code>. Typically, you would pass an option to your compiler to do
this.</p>
<p>You can also enable this feature for individual enums instead, by declaring them
using the alternative <code>SLOW_ENUM</code> macro.</p>
<p>The feature is disabled because it increases compilation times by a factor of
about 4. Compilation is still relatively fast &mdash; you need about a dozen
slow enums to get the same penalty as including <code>iostream</code> &mdash; but it is
a steep penalty nonetheless. I don't think most people need this feature most of
the time, so it's too high a price to pay. If I improve compilation times to the
point where compile-time name trimming can be the default, I will simply
redefine <code>SLOW_ENUM</code> as <code>BETTER_ENUM</code> and deprecate it, so your code will still
work.</p>
<a id="StrictConversions"></a><h3>Strict conversions</h3>
<p>This disables implicit conversions to underlying integral types. At the moment,
you can only enable this globally for all enums, by defining
<code>BETTER_ENUMS_STRICT_CONVERSION</code> before including <code>enum.h</code>.</p>
<p>The reason Better Enums have implicit conversions to integral types in the first
place is that in <span class="cpp">C++</span><span class="eleven">98</span>, Better Enums have to be implicitly convertible to their
member <a href="ApiReference.html#Typedef_enumerated"><code>_enumerated</code></a> types to
be <a href="tutorial/SafeSwitch.html">usable</a> in <code>switch</code> statements. It is
possible to avoid this in <span class="cpp">C++</span><span class="eleven">11</span> and convert to <code>enum class</code> types instead, but
at the cost of breaking interface compatibility with <span class="cpp">C++</span><span class="eleven">98</span>.</p>
<ul>
<li>The "weaker" incompatibility is that you could write a bunch of <span class="cpp">C++</span><span class="eleven">98</span> code
that relies on implicit integer conversions, and then try to switch to
<span class="cpp">C++</span><span class="eleven">11</span>. The code would then fail to compile. An example where implicit
conversions are an "advantage" is when using Better Enums as arguments to
the methods of <code>std::bitset</code>. I could have ignored this problem by declaring
usage of implicit integer conversions unsupported, but in light of the next
issue, I decided not to do that.</li>
<li>The "stronger" incompatibility is a difference in how <code>switch</code> cases must be
written. The syntaxes for the two variants, implicitly-converting and
strict, are mutually exclusive. They differ by a <code>+</code> character.</li>
</ul>
<p>Here they are:</p>
<pre>// Default variant
<em>switch</em> (<em>channel</em>) {
case Channel::Red: break;
case Channel::Green: break;
case Channel::Blue: break;
}
// Strict variant
<em>switch</em> (<em>channel</em>) {
case <em>+</em>Channel::Red: break;
case <em>+</em>Channel::Green: break;
case <em>+</em>Channel::Blue: break;
}</pre><a id="InjectingTokens"></a><h3>Injecting tokens</h3>
<p>You can define <code>BETTER_ENUMS_CLASS_ATTRIBUTE</code> before declaring a Better Enum, to
inject tokens into the class declaration. For example, in</p>
<pre>#define <em>BETTER_ENUMS_CLASS_ATTRIBUTE</em> <em>__attribute__(foo)</em>
<em>BETTER_ENUM</em>(<em>Channel</em>, int, Red, Green, Blue)</pre><p>The resulting enum declaration will begin with</p>
<pre>class <em>__attribute__(foo)</em> <em>Channel</em> {</pre>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

134
Performance.html Normal file
View File

@ -0,0 +1,134 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Performance - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/Performance.html" />
<meta name="description" content="Better Enums compilation speed and performance testing results." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="index.html">Home</a>
<a href="tutorial/HelloWorld.html">Tutorial</a>
<a href="ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<h2>Performance</h2>
<p>A basic performance test is run on
<a href="CompilerSupport.html#TestedConfigurations">every compiler tested</a>. It
doesn't try to be very accurate &mdash; it just stress-tests the compiler once
to get a rough idea of how long it takes to compile Better Enums.</p>
<p>The files compared in the test are as follows:</p>
<ul>
<li><a href="https://github.com/aantron/better-enums/blob/0.11.3/test/performance/4-declare_enums.cc">One file</a> includes
<code>enum.h</code> and declares 647 constants across 36 Better Enums.</li>
<li>The <a href="https://github.com/aantron/better-enums/blob/0.11.3/test/performance/5-iostream.cc">other file</a> <em>only</em>
includes <code>iostream</code> and does nothing with it.</li>
</ul>
<p>The argument is that if compiling a bunch of Better Enums is faster, or about as
fast as, including a single standard header such as <code>iostream</code>, then Better
Enums is fast enough for general use.</p>
<p>Results are given for select compilers and
<a href="CompilerSupport.html#CompileTimeReflectionConfigurations">configurations</a>
as ratios of how long it took to compile the Better Enums file to how long it
took to compile the <code>iostream</code> file. The less the ratio, the better. Ratios less
than 1 mean the enums compiled faster, and ratios greater than 1 mean <code>iostream</code>
compiled faster.</p>
<ul>
<li>clang 3.6, fast <code>constexpr</code>: 0.66</li>
<li>clang 3.6, full <code>constexpr</code>: 2.25</li>
<li>gcc 5.1, fast <code>constexpr</code>: 1.58</li>
<li>gcc 5.1, full <code>constexpr</code>: 4.23</li>
<li>VC2015RC, <span class="cpp">C++</span><span class="eleven">98</span>: 1.18</li>
</ul>
<p>The time to merely include <code>enum.h</code> vary widely by compiler, with clang being
by far the fastest. The ratios to <code>iostream</code> are given below.</p>
<ul>
<li>clang 3.6: 0.15</li>
<li>gcc 5.1: 0.77</li>
<li>VC2015RC: 0.82</li>
</ul>
<p>On my test machines, clang processed the file in 40ms, gcc took 230ms, and
VC2015 took 820ms. The first two are comparable to each other, but VC2015 runs
on a different machine.</p>
<hr>
<p>In general, I am very sensitive to performance. Better Enums was originally
developed in the context of a commercial project where slow running times <em>and</em>
slow compilation times were unacceptable. I am continuing to develop it in this
spirit.</p>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

595
better-enums.css Normal file
View File

@ -0,0 +1,595 @@
body {
margin: 0;
color: #333;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 18px;
font-weight: 300;
}
pre, code, samp, h4, .contents ul {
font-family:
Consolas, "Liberation Mono", Menlo, "Courier New", Courier, monospace;
}
h1, .splash-text .self, nav .self {
font-family: Georgia, Times, "Times New Roman", serif;
}
pre {
background-color: #477093;
padding: 1.5em 20px;
border-radius: 5px;
overflow: auto;
color: rgba(255, 255, 255, 0.6);
font-size: 78%;
max-width: 84ex;
margin-left: 1em;
}
pre em {
font-style: normal;
text-shadow: 0 -1px grey;
color: white;
}
pre.comment {
background-color: #EEF4F9;
color: #888;
border: 1px dashed #477093;
}
pre.comment em {
color: #333;
text-shadow: none;
}
code, samp {
background-color: #EEF4F9;
padding: 1px 3px;
border-radius: 3px;
font-size: 78%;
}
.container {
margin-left: 150px;
margin-right: 150px;
}
.main .container > * {
max-width: 41em;
}
.index .main .container > * {
max-width: none;
}
.main .container > .contents {
max-width: none;
}
@media (max-width: 1400px) {
.container {
margin-left: auto;
margin-right: auto;
width: 1100px;
}
}
@media (max-width: 1120px) {
.container {
margin-left: 10px;
margin-right: 10px;
width: auto;
}
}
nav {
position: fixed;
width: 100%;
z-index: 1;
border-bottom: 1px solid #68a;
color: white;
opacity: 0.95;
}
nav, .spacer {
padding: 0.75em 0;
font-size: 14px;
background-color: #222;
}
nav > * > span {
float: right;
opacity: 0.9;
margin-right: 1em;
}
nav .self {
font-size: 16px;
padding-right: 0.5em;
}
nav a {
margin-right: 2em;
}
nav a.first {
font-weight: 600;
font-size: 16px;
}
@media (max-width: 560px) {
nav {
position: initial;
}
.spacer {
display: none;
}
}
header {
background-color: #4C6F8C;
background: linear-gradient(#395E7E, #4A79A0);
color: white;
padding: 50px 0;
}
h1 {
margin: 0;
font-size: 60px;
font-weight: normal;
text-shadow: -2px 2px rgba(0, 0, 0, 0.3);
}
header section {
float: left;
}
header section.buttons, header section.notes {
float: right;
margin-top: 1.75em;
margin-left: 20px;
}
header section.notes {
max-width: 20em;
font-size: 75%;
margin-right: 10px;
opacity: 0.7;
}
header section.notes p {
margin: 0.35em 0.35em;
}
header section.notes code {
background-color: transparent;
}
header h2 {
margin: 0;
font-size: 24px;
font-weight: 100;
position: relative;
left: 3px;
}
header h3 {
margin: 0;
font-size: 14px;
font-weight: 300;
position: relative;
left: 4px;
opacity: 0.5;
}
.buttons a {
display: block;
background-color: rgba(255, 255, 255, 0.2) !important;
width: 10em;
text-align: center;
margin-bottom: 0.5em;
padding: 0.25em 0;
border-radius: 4px;
}
.buttons a:hover {
background-color: white !important;
color: #395E7E;
}
@media (max-width: 1000px) {
header .notes {
display: none;
}
header .buttons {
margin-right: 2em;
}
}
@media (max-width: 660px) {
header .buttons {
display: none;
}
}
h2 {
margin-top: 2em;
font-size: 36px;
font-weight: 300;
}
hr {
border: none;
height: 40px;
}
footer {
font-size: 14px;
margin-top: 100px;
margin-bottom: 20px;
opacity: 0.5;
}
a {
text-decoration: none;
color: white;
/*background-color: red;*/
}
a[href=""] {
color: white !important;
/*background-color: red !important;*/
}
a:hover {
text-decoration: underline;
}
header a:hover {
text-decoration: none;
}
.main {
margin-top: 50px;
}
.main a[href], footer a[href] {
background-color: #edd;
color: #844;
letter-spacing: -0.5px;
padding: 0 2px;
border-radius: 3px;
}
header a[href], nav a[href] {
color: inherit;
background-color: transparent;
letter-spacing: inherit;
}
a[href] code {
background-color: transparent;
}
span.cpp, span.cc {
font-size: 90%;
}
span.eleven {
font-size: 85%;
}
span#note:target {
background-color: yellow;
}
.pane {
float: left;
width: 49%;
}
.hack {
clear: both;
}
.pane.left > * {
margin-right: 10px;
}
.pane.right > * {
margin-left: 10px;
}
.main h3 {
font-size: 30px;
margin-top: 2em;
color: black;
}
h3 {
margin-top: 0;
margin-bottom: 0;
font-weight: inherit;
}
h3.contents {
font-size: 22px;
}
.pane pre {
font-size: 14px;
padding-top: 20px;
padding-bottom: 20px;
line-height: 1.15;
}
header {
overflow: hidden;
}
header .container {
position: relative;
}
div.back {
position: absolute;
bottom: -0.35em;
left: -40px;
font-size: 288px;
font-weight: bold;
letter-spacing: 20px;
opacity: 0.1;
text-shadow: -20px 20px #444;
white-space: nowrap;
}
.panes {
clear: both;
margin-top: 2em;
margin-bottom: 2em;
overflow: auto;
}
.tutorial-footer {
margin-top: 4em;
}
.tutorial-footer .next {
font-weight: 100;
font-size: 24px;
}
.tutorial-footer .next a[href] {
font-weight: 300;
}
li {
margin-top: 5px;
}
.blurbs {
padding-left: 0;
list-style-type: none;
margin-top: 30px;
}
.blurbs > li {
float: left;
min-height: 5em;
}
@media (min-width: 1076px) {
.blurbs > li {
width: 28%;
margin-right: 4%;
}
.blurbs > li.zero-mod-three {
clear: both;
margin-left: 2%;
}
}
@media (max-width: 1075px) {
.blurbs > li {
width: 45%;
margin-right: 4%;
}
.blurbs > li.zero-mod-two {
clear: both;
margin-left: 2%;
}
}
@media (max-width: 620px) {
.blurbs > li {
float: none;
width: 100%;
min-height: 3em;
}
.blurbs > li.zero-mod-two {
margin-left: 0;
margin-right: 0;
}
}
.blurbs strong {
font-weight: inherit;
font-size: 110%;
}
.blurbs em {
display: block;
margin-bottom: 1em;
font-size: 80%;
font-style: normal;
}
.act strong {
font-weight: bold;
font-size: 120%;
}
.act strong code {
font-size: 110%;
}
.resources > li {
margin-bottom: 3.5em;
}
.resources li ul, .resources li ol {
margin-top: 1.5em;
padding-left: 25px;
}
.splash-text {
padding-top: 1em;
font-size: 150%;
font-weight: normal;
color: #555;
}
.splash-text em {
border-bottom: 1px solid #888;
}
.splash-text .self {
color: #777;
letter-spacing: 0;
}
.splash {
float: right;
text-align: center;
white-space: nowrap;
}
.splash pre {
display: inline-block;
}
.splash pre.left {
text-align: right;
color: black;
font-weight: bold;
background-color: transparent;
padding-right: 0;
}
.splash pre.right {
text-align: left;
background-color: black;
}
@media (max-width: 1000px) {
.splash {
float: none;
margin-left: -10%;
}
}
@media (max-width: 700px) {
.splash {
margin-left: 0;
}
.splash pre.left {
display: none;
}
}
a[id] {
display: block;
position: relative;
top: -25px;
}
h4 {
font-weight: normal;
margin-top: 3em;
letter-spacing: -1px;
color: #888;
padding-top: 1em;
white-space: nowrap;
font-size: 125%;
}
h4 em {
color: #555;
font-style: normal;
font-weight: bold;
}
.api ul.contents {
-webkit-columns: 300px 3;
-moz-columns: 300px 3;
columns: 300px 3;
}
.api ul.contents > li {
-webkit-column-break-inside: avoid;
page-break-inside: avoid;
break-inside: avoid;
}
.main h3 {
margin-top: 4em;
clear: both;
}
h3.contents {
margin-top: 2em;
}
.index .main h3 {
margin-top: 2em;
}
.api .contents ul {
font-size: 75%;
}
.api .contents > li {
margin-top: 0;
padding-bottom: 1em;
}
.buttons-bar {
background-color: #f4f4f4;
padding-top: 0.5em;
padding-bottom: 0.5em;
height: 20px;
}
.buttons-bar a img {
margin-right: 25px;
}
.buttons-bar iframe.gh-button {
width: 95px;
}
.buttons-bar .tweet-share,
.buttons-bar .gh-button {
display: none;
}
.index .buttons-bar .tweet-share,
.index .buttons-bar .gh-button {
display: initial;
}
.buttons-bar iframe.gh-watch {
width: 103px;
}
.external {
font-size: 75%;
}

154
demo/BitSets.html Normal file
View File

@ -0,0 +1,154 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Bit sets - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/demo/BitSets.html" />
<meta name="description" content="Finding the maximum value of a Better Enum for use in declaring
statically-sized bit set types." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="../better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="../index.html">Home</a>
<a href="../tutorial/HelloWorld.html">Tutorial</a>
<a href="../ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="../index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<p>
This is an example of code you can write on top of Better Enums. It's a valid
program &mdash; you can <a href="https://github.com/aantron/better-enums/blob/0.11.3/example/103-bitset.cc">download</a> it and try it out. The
program is also part of the test suite.
</p>
<h2>Bit sets</h2>
<p>If you want to use <code>std::bitset</code> or a similar library to have enums be keys into
a bit set, you need to know the number of bits at compile time. You can easily
automate this with Better Enums, even when constants are not declared in
increasing order.</p>
<hr>
<p>We simply need to find the maximum value of any given enum type.</p>
<pre>#include &lt;bitset&gt;
#include &lt;iostream&gt;
<em>#include &lt;enum.h&gt;</em>
template &lt;<em>typename Enum</em>&gt;
constexpr <em>Enum max_loop</em>(Enum accumulator, size_t index)
{
return
<em>index &gt;= Enum::_size() ? accumulator :
Enum::_values()[index] &gt; accumulator ?
max_loop&lt;Enum&gt;(Enum::_values()[index], index + 1) :
max_loop&lt;Enum&gt;(accumulator, index + 1)</em>;
}
template &lt;<em>typename Enum</em>&gt;
constexpr <em>Enum max</em>()
{
return <em>max_loop&lt;Enum&gt;(Enum::_values()[0], 1)</em>;
}</pre><p>And use that to declare a bit set template:</p>
<pre>template &lt;<em>typename Enum</em>&gt;
using <em>EnumSet</em> = <em>std::bitset</em>&lt;<em>max&lt;Enum&gt;()._to_integral()</em> + <em>1</em>&gt;;</pre><p>Now, we can have bit sets that are wide enough to hold whatever range we
declared. We just declare enums, and the numeric values of their constants will
be bit indices. The rest is straightforward.</p>
<pre>BETTER_ENUM(<em>EFLAGS</em>, int,
<em>Carry</em>, <em>Parity</em> = 2, <em>Adjust</em> = 4, <em>Zero</em>, <em>Sign</em>, <em>Trap</em>, <em>Interrupt</em>, <em>Direction</em>,
<em>Overflow</em>, <em>NestedTask</em> = 14, <em>Resume</em> = 16, <em>V8086</em>, <em>AlignmentCheck</em>,
<em>CPUIDPresent</em> = 21)
int main()
{
<em>EnumSet</em>&lt;<em>EFLAGS</em>&gt; eflags = <em>1 &lt;&lt; EFLAGS::Carry</em> | <em>1 &lt;&lt; EFLAGS::Zero</em>;
if (eflags.test(<em>EFLAGS::Carry</em>))
eflags.set(<em>EFLAGS::Trap</em>);
std::cout &lt;&lt; <em>eflags</em> &lt;&lt; std::endl;
return 0;
}</pre><hr>
<p>If we want bit sets of fixed known width instead, we can use the code above to
check that we haven't declared any bit indices out of range:</p>
<pre class="comment">static_assert(max&lt;EFLAGS&gt;()._to_integral() &lt; 32,
"some bit indices are out of range");</pre>
<section class="tutorial-footer">
<p class="up">
Return to the <a href="../index.html#CompileTimeDemos">demo index</a>.
</p>
</section>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

156
demo/C++17Reflection.html Normal file
View File

@ -0,0 +1,156 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>C++17 reflection - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/demo/C++17Reflection.html" />
<meta name="description" content="Approximate implementation of N4428 enum reflection based on
Better Enums." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="../better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/master/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="../index.html">Home</a>
<a href="../tutorial/HelloWorld.html">Tutorial</a>
<a href="../ApiReference.html">Reference</a>
<a href="../Contact.html">Contact</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="../index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.10.1</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/master/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<p>
This page is an advanced demo showing the kind of code you can write on top of
Better Enums. It's a valid program &mdash; you can
<a href="https://github.com/aantron/better-enums/blob/master/example/105-c++17-reflection.cc">download</a> it and try it out. The program runs as part of
the automated test suite.
</p>
<h2>C++17 reflection</h2>
<p>Better Enums can be used to approximately implement the enums portion of the
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4428.pdf"><span class="cpp">C++</span><span class="eleven">17</span> reflection proposal N4428</a> in <span class="cpp">C++</span><span class="eleven">11</span>. The implementation is
<em>approximate</em> in the following senses:</p>
<ul>
<li>It only applies to Better Enums, not built-in enums.</li>
<li><code>enum_traits&lt;E&gt;::enumerators::get&lt;I&gt;::identifier</code> is a non-<code>constexpr</code>
function rather than a <code>constexpr</code> variable. I could make it a <code>constexpr</code>
variable as in the proposal, but that requires
<a href="../OptInFeatures.html#CompileTimeNameTrimming">compile-time name trimming</a> to be enabled for the Better Enum
on which <code>get</code> is used. Since that's an opt-in feature, I can't guarantee it.
I preferred not to write feature-detection code, in order to keep the
implementation simple.</li>
<li>The return type of <code>identifier</code> is <code>const char*</code> instead of the proposed
<code>std::string_literal</code>, because I don't have an implementation of the latter
available. I'm also ignoring the requirements on encoding, and just taking
whatever the preprocessor provides.</li>
</ul>
<p>With that out of the way, we can look at a simple example.</p>
<hr>
<p>The implementation is defined in <a href="https://github.com/aantron/better-enums/blob/master/extra/better-enums/n4428.h"><code>extra/better-enums/n4428.h</code></a>. Let's
assume that <code>extra/</code> has been added as a directory to search for include files.</p>
<pre>#include &lt;iostream&gt;
<em>#include</em> &lt;<em>enum.h</em>&gt;
<em>#include</em> &lt;<em>better-enums/n4428.h</em>&gt;</pre><hr>
<p>Let's declare an enum:</p>
<pre><em>ENUM</em>(<em>Channel</em>, <em>char</em>, <em>Red</em> = <em>1</em>, <em>Green</em>, <em>Blue</em>)</pre><p>N4428 proposes three <code>constexpr</code> traits, of which we have two implemented
exactly &mdash; that is, as <code>constexpr</code>:</p>
<pre><em>constexpr std::size_t size</em> =
<em>std</em>::<em>enum_traits</em>&lt;<em>Channel</em>&gt;::<em>enumerators</em>::<em>size</em>;
<em>constexpr Channel value_0</em> =
<em>std</em>::<em>enum_traits</em>&lt;<em>Channel</em>&gt;::<em>enumerators</em>::<em>get</em>&lt;<em>0</em>&gt;::<em>value</em>;
<em>constexpr Channel value_1</em> =
<em>std</em>::<em>enum_traits</em>&lt;<em>Channel</em>&gt;::<em>enumerators</em>::<em>get</em>&lt;<em>1</em>&gt;::<em>value</em>;</pre><p>Let's check the results:</p>
<pre>static_assert(<em>size</em> == <em>3</em>, "");
static_assert(<em>value_0</em> == +<em>Channel::Red</em>, "");
static_assert(<em>value_1</em> == +<em>Channel::Green</em>, "");</pre><p>Finally, we can try using <code>identifier</code>:</p>
<pre>int main()
{
std::cout
&lt;&lt; <em>std</em>::<em>enum_traits</em>&lt;<em>Channel</em>&gt;::<em>enumerators</em>::<em>get</em>&lt;<em>2</em>&gt;::<em>identifier</em>()
&lt;&lt; std::endl;
return 0;
}</pre><p>That prints <code>Blue</code>, as you would expect.</p>
<section class="tutorial-footer">
<p class="up">
Return to the <a href="../index.html#CompileTimeDemos">demo index</a>.
</p>
</section>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015 Anton Bachin. Released under the BSD 2-clause license.
See
<a href="https://github.com/aantron/better-enums/blob/master/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.10.1.
</div>
</footer>
</body>
</html>

View File

@ -0,0 +1,224 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>C++17 reflection proposal - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/demo/C++17ReflectionProposal.html" />
<meta name="description" content="Approximate implementation of N4428 enum reflection based on
Better Enums." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="../better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="../index.html">Home</a>
<a href="../tutorial/HelloWorld.html">Tutorial</a>
<a href="../ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="../index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<p>
This is an example of code you can write on top of Better Enums. It's a valid
program &mdash; you can <a href="https://github.com/aantron/better-enums/blob/0.11.3/example/105-c++17-reflection.cc">download</a> it and try it out. The
program is also part of the test suite.
</p>
<h2>C++17 reflection proposal</h2>
<p><em>You can try this demo <a href="http://melpon.org/wandbox/permlink/QelcwZNLi4gIx8Ux">live online</a>.</em></p>
<p>Better Enums can be used to implement the enums portion of the
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4428.pdf"><span class="cpp">C++</span><span class="eleven">17</span> reflection proposal N4428</a> in <span class="cpp">C++</span><span class="eleven">11</span>. N4428 proposes the
following traits interface:</p>
<pre class="comment"><em>namespace std {
template &lt;typename E&gt;
struct enum_traits {
struct enumerators {
constexpr static size_t size;
template &lt;size_t I&gt;
struct get {
constexpr string_literal identifier;
constexpr static E value;
};
};
};
}</em></pre><p>So, the basic usage would be:</p>
<pre class="comment"><em>enum class Foo {A, B, C};
constexpr size_t size =
std::enum_traits&lt;Foo&gt;::enumerators::size;
constexpr Foo value_0 =
std::enum_traits&lt;Foo&gt;::enumerators::get&lt;0&gt;::value;
constexpr string_literal name_1 =
std::enum_traits&lt;Foo&gt;::enumerators::get&lt;1&gt;::identifier;</em></pre><p>Resulting in the values <code>3</code>, <code>Foo::A</code>, and <code>"B"</code>, respectively.</p>
<hr>
<p>The interface is implemented in the optional header file
<a href="https://github.com/aantron/better-enums/blob/0.11.3/extra/better-enums/n4428.h"><code>extra/better-enums/n4428.h</code></a>. There is a necessary difference: the
interface is only available for enums declared through the <code>BETTER_ENUM</code> macro.
This is because the macro is what generates the information necessary for
reflection.</p>
<a id="Demo"></a><h3>Demo</h3>
<p>So, with that out of the way, we can do a little test. Let's assume that
<code>extra/</code> has been added as a directory to search for include files.</p>
<pre>#ifndef BETTER_ENUMS_CONSTEXPR_TO_STRING
#define BETTER_ENUMS_CONSTEXPR_TO_STRING
#endif
#include &lt;iostream&gt;
<em>#include</em> &lt;<em>enum.h</em>&gt;
<em>#include</em> &lt;<em>better-enums/n4428.h</em>&gt;</pre><hr>
<p>Let's declare an enum:</p>
<pre><em>BETTER_ENUM</em>(<em>Channel</em>, <em>char</em>, <em>Red</em> = <em>1</em>, <em>Green</em>, <em>Blue</em>)</pre><p>...and try N4428:</p>
<pre>constexpr std::size_t <em>size</em> =
<em>std</em>::<em>enum_traits</em>&lt;<em>Channel</em>&gt;::<em>enumerators</em>::<em>size</em>;
constexpr Channel <em>value_0</em> =
<em>std</em>::<em>enum_traits</em>&lt;<em>Channel</em>&gt;::<em>enumerators</em>::<em>get</em>&lt;<em>0</em>&gt;::<em>value</em>;
constexpr Channel <em>value_1</em> =
<em>std</em>::<em>enum_traits</em>&lt;<em>Channel</em>&gt;::<em>enumerators</em>::<em>get</em>&lt;<em>1</em>&gt;::<em>value</em>;
constexpr const char *<em>identifier_2</em> =
<em>std</em>::<em>enum_traits</em>&lt;<em>Channel</em>&gt;::<em>enumerators</em>::<em>get</em>&lt;<em>2</em>&gt;::<em>identifier</em>;</pre><p>...and check the results:</p>
<pre>static_assert(<em>size</em> == <em>3</em>, "");
static_assert(<em>value_0</em> == +<em>Channel::Red</em>, "");
static_assert(<em>value_1</em> == +<em>Channel::Green</em>, "");
int main()
{
std::cout &lt;&lt; <em>identifier_2</em> &lt;&lt; std::endl;
return 0;
}</pre><p>That prints <code>Blue</code>, as you would expect.</p>
<a id="Quirk"></a><h3>Quirk</h3>
<p>The reason for the <code>#define</code> in the code above is that there is one quirk:
the interface above is available only for Better Enums for which
<a href="../OptInFeatures.html#CompileTimeNameTrimming">compile-time name trimming</a> is enabled &mdash; those declared when
<code>BETTER_ENUMS_CONSTEXPR_TO_STRING</code> was defined, or declared with the <code>SLOW_ENUM</code>
variant of <code>BETTER_ENUM</code>. As mentioned on the linked page, the reason
compile-time name trimming is not the default is that, while still pretty fast,
it is four times slower than program-startup-time name trimming. The latter is
the default.</p>
<p>Despite the above, a variation on the interface is available for enums without
compile-time name trimming:</p>
<pre class="comment"><em>namespace std {
template &lt;typename E&gt;
struct enum_traits {
struct enumerators {
constexpr static size_t size;
template &lt;size_t I&gt;
struct get {
constexpr const char *identifier;
constexpr static E value;
};
</em>// For enums without compile-time name trimming.<em>
template &lt;size_t I&gt;
struct get_alt {
static const char* identifier();
constexpr static E value;
};
};
};
}</em></pre><p>As you can see, the difference is that <code>identifier</code> is a non-<code>constexpr</code>
function, and you have to access it through <code>get_alt&lt;I&gt;</code>.</p>
<pre class="comment">// Without compile-time name trimming.
<em>BETTER_ENUM(Depth, int, HighColor, TrueColor)
int main()
{
std::cout
&lt;&lt; std::enum_traits&lt;Depth&gt;::enumerators::get_alt&lt;1&gt;::identifier()
&lt;&lt; std::endl;
return 0;
}</em></pre><a id="TheFuture"></a><h3>The future</h3>
<p>N4428 is the fourth in a series of revisions: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3815.html">N3815</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4027.pdf">N4027</a>,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4113.pdf">N4113</a>, N4428. If there are more revisions that change the proposal for
enums, I will try to implement those as well.</p>
<section class="tutorial-footer">
<p class="up">
Return to the <a href="../index.html#CompileTimeDemos">demo index</a>.
</p>
</section>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

View File

@ -0,0 +1,242 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Non-integral underlying types - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/demo/NonIntegralUnderlyingTypes.html" />
<meta name="description" content=""Using Better Enums with non-integral underlying types."" />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="../better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/master/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="../index.html">Home</a>
<a href="../tutorial/HelloWorld.html">Tutorial</a>
<a href="../ApiReference.html">Reference</a>
<a href="../Contact.html">Contact</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="../index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.10.1</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/master/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<p>
This page is an advanced demo showing the kind of code you can write on top of
Better Enums. It's a valid program &mdash; you can
<a href="https://github.com/aantron/better-enums/blob/master/example/102-any-underlying.cc">download</a> it and try it out. The program runs as part of
the automated test suite.
</p>
<h2>Non-integral underlying types</h2>
<p>The underlying type of a Better Enum doesn't have to be an integral type. It can
be any literal type <code>T</code>, as long as you provide a <code>constexpr</code> two-way mapping
between <code>T</code> and an integral type of your choosing. This also works in <span class="cpp">C++</span><span class="eleven">98</span>
&mdash; though then, of course, <code>T</code> doesn't have to be literal and the mapping
doesn't have to be <code>constexpr</code>. In <span class="cpp">C++</span><span class="eleven">98</span>, everything involving <code>T</code> will simply
be done by Better Enums at run time.</p>
<p>This feature is semi-experimental. I am considering relaxing the requirements on
<code>T</code> so that it doesn't have to be literal. I can use a <code>reinterpret_cast</code> to
make a mapping automatically. This will make non-integral underlying types
easier to use, but will also prevent usage at compile time, which unfortunately
has structural consequences for the implementation of Better Enums, and
additional semantic consequences for usage, even at run time.</p>
<p>In the meantime, here's how to have a non-integral underlying type in the
current version.</p>
<pre>#include &lt;iostream&gt;
#include &lt;enum.h&gt;
typedef unsigned char uint8_t; // &lt;cstdint&gt; not in C++98.
// The underlying type. A color triplet.
<em>struct html_color {
uint8_t r, g, b;
constexpr html_color(uint8_t _r, uint8_t _g, uint8_t _b) :
r(_r), g(_g), b(_b) { }
};</em>
// The mapping. It just stuffs bits to get the same effect as
// reinterpret_cast, except reinterpret_cast is not available in constexpr
// functions, so we have to write the bit manipulations out. On modern
// C++11 compilers, you don't have to enter the better_enums namespace like
// this - you can just do
// struct ::better_enums::integral_mapping&lt;html_color&gt; { ...
namespace better_enums {
<em>template &lt;&gt;
struct integral_mapping&lt;html_color&gt; {
using integral_representation = unsigned int;
constexpr static html_color from_integral(unsigned int i)
{ return html_color(i &gt;&gt; 16 &amp; 0xff, i &gt;&gt; 8 &amp; 0xff, i &amp; 0xff); }
constexpr static unsigned int to_integral(html_color c)
{ return (unsigned int)c.r &lt;&lt; 16 | (unsigned int)c.g &lt;&lt; 8 | c.b; }
};</em>
}
// The enum itself.
<em>ENUM(Color, html_color,
darksalmon = 0xc47451, purplemimosa = 0x9e7bff, slimegreen = 0xbce954)</em></pre><p>Now, we can do:</p>
<pre>int main()
{
<em>Color color = Color::darksalmon</em>;
std::cout &lt;&lt; std::hex;
std::cout &lt;&lt; "Red component: " &lt;&lt; <em>(int)color-&gt;r</em> &lt;&lt; std::endl;
std::cout &lt;&lt; "Green component: " &lt;&lt; <em>(int)color-&gt;g</em> &lt;&lt; std::endl;
std::cout &lt;&lt; "Blue component: " &lt;&lt; <em>(int)color-&gt;b</em> &lt;&lt; std::endl;
std::cout &lt;&lt; <em>color._to_string()</em> &lt;&lt; std::endl;
<em>switch (color)</em> {
<em>case Color::darksalmon</em>: return 0;
<em>case Color::purplemimosa</em>: return 1;
<em>case Color::slimegreen</em>: return 2;
}
return 0;
}</pre><p>This prints each component, the name of the color (<code>"darksalmon"</code>), and then
exits from the <code>switch</code> with status 0.</p>
<a id="ConstructorsInInitializers"></a><h3>Constructors in initializers</h3>
<p>The above declaration used only numbers in initializers, but it is actually
possible to use constructors of <code>html_color</code>. We have to add a <code>constexpr</code>
converting operator directly to <code>html_color</code>, however:</p>
<pre class="comment">struct better_html_color {
uint8_t r, g, b;
constexpr better_html_color(uint8_t _r, uint8_t _g, uint8_t _b) :
r(_r), g(_g), b(_b) { }
<em>// This is new:
constexpr operator unsigned int() const
{ return (unsigned int)r &lt;&lt; 16 | (unsigned int)g &lt;&lt; 8 | b; }</em>
};
namespace better_enums {
template &lt;&gt;
struct integral_mapping&lt;better_html_color&gt; {
using integral_representation = unsigned int;
constexpr static better_html_color from_integral(unsigned int i)
{
return better_html_color(i &gt;&gt; 16 &amp; 0xff, i &gt;&gt; 8 &amp; 0xff, i &amp; 0xff);
}
constexpr static unsigned int to_integral(better_html_color c)
{ return (unsigned int)c.r &lt;&lt; 16 | (unsigned int)c.g &lt;&lt; 8 | c.b; }
};
}</pre><p>This allows:</p>
<pre class="comment">ENUM(BetterColor, better_html_color,
darksalmon = 0xc47451, purplemimosa = 0x9e7bff, slimegreen = 0xbce954,
<em>celeste = better_html_color(0x50, 0xeb, 0xec)</em>)</pre><p>If you can't edit your literal type to add this converting operator, or don't
want to for type safety reasons, you can achieve a similar effect by declaring
an intermediate type <code>U</code> that <code>html_color</code> can convert to, that can convert to
the integral type. Then, cast your constructor call to <code>U</code>. The type <code>U</code> is for
declarations only.</p>
<p>Constructors in initializers require <span class="cpp">C++</span><span class="eleven">11</span>. Also, g++ doesn't support this
before 5.1.</p>
<a id="LettingTheCompilerEnumerateYourType"></a><h3>Letting the compiler enumerate your type</h3>
<p>Of course, as long as the values are valid, you can let the compiler enumerate
your type as in a regular enum, by omitting initializers:</p>
<pre class="comment"><em>ENUM(FD, file_descriptor, STDIN, STDOUT, STDERR, SomePipeYourDaemonHas, ...)</em></pre><p>Here, <code>FD::STDIN</code> maps to the integral representation 0, <code>STDOUT</code> to 1, and so
on.</p>
<a id="Discussion"></a><h3>Discussion</h3>
<p>This feature is still semi-experimental, though I expect it to remain stable,
except perhaps that I will make it possible to infer the type
<code>integral_representation</code>.</p>
<p>Any opinions are welcome.</p>
<ul>
<li>The main reason Better Enums needs you to supply and explicit mapping is
because it can't just get the "bits" of objects of underlying type in
<code>constexpr</code> code. Both <code>reinterpret_cast</code> and union abuse seem to be forbidden
in <code>constexpr</code> functions.</li>
<li>There is currently no way to have two different integral representaitons for
the same underlying type in different enums. I don't think that's a major use
case at this point, however.</li>
</ul>
<section class="tutorial-footer">
<p class="up">
Return to the <a href="../index.html#CompileTimeDemos">demo index</a>.
</p>
</section>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015 Anton Bachin. Released under the BSD 2-clause license.
See
<a href="https://github.com/aantron/better-enums/blob/master/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.10.1.
</div>
</footer>
</body>
</html>

225
demo/SemiQuine.html Normal file
View File

@ -0,0 +1,225 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Semi-quine - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/demo/SemiQuine.html" />
<meta name="description" content="Have a Better Enum print its own definition. Shows how to
compute the amount of memory necessary from the reflective information provided
by a Better Enum." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="../better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="../index.html">Home</a>
<a href="../tutorial/HelloWorld.html">Tutorial</a>
<a href="../ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="../index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<p>
This is an example of code you can write on top of Better Enums. It's a valid
program &mdash; you can <a href="https://github.com/aantron/better-enums/blob/0.11.3/example/104-quine.cc">download</a> it and try it out. The
program is also part of the test suite.
</p>
<h2>Semi-quine</h2>
<p>Let's make a Better Enum assemble its own definition in memory. It won't be
literally as defined, since we will lose the exact initializer expressions, but
we will be able to preserve the numeric values. We will reserve the memory
buffer for the definition at compile time.</p>
<p>Ok, so it's not really a quine, because we won't be writing all the code needed
to generate the definition to the buffer as well. And, there are better ways to
dump the definition than shown here. You could simply define a macro that
expands to an <code>BETTER_ENUM</code> declaration and also stringizes it.</p>
<p>But that's not the point here. The point of this page is to show some of the
reflective capabilities of Better Enums, so you can adapt them for cases where a
macro is not sufficient :)</p>
<p><a id="contents"></a><h3 class="contents">Contents</h3><ul class="contents"><li><a href="#ComputingTheSizeOfTheBuffer">Computing the size of the buffer</a></li><li><a href="#FormattingTheEnums">Formatting the enums</a></li><li><a href="#CheckingOurWork">Checking our work</a></li></ul></p>
<hr>
<pre>#include &lt;cassert&gt;
#include &lt;cstdio&gt;
#include &lt;iostream&gt;</pre><hr>
<p>First, we will need
<a href="../OptInFeatures.html#CompileTimeNameTrimming">full compile-time reflection</a>,
since we will be calling <code>_to_string</code>. Let's make sure it's enabled by defining
<code>BETTER_ENUMS_CONSTEXPR_TO_STRING</code> before including <code>enum.h</code>:</p>
<pre>#ifndef <em>BETTER_ENUMS_CONSTEXPR_TO_STRING</em>
#define <em>BETTER_ENUMS_CONSTEXPR_TO_STRING</em>
#endif
<em>#include &lt;enum.h&gt;</em></pre><p>Now, let's declare some enums to dump later:</p>
<pre>BETTER_ENUM(<em>Channel</em>, int, Red, Green, Blue)
BETTER_ENUM(<em>Depth</em>, int, TrueColor = 1, HighColor = 0)</pre><a id="ComputingTheSizeOfTheBuffer"></a><h3>Computing the size of the buffer</h3>
<p>First, we need to be able to get the length of each declaration above. We will
assume that the underlying type is always <code>int</code>, and that the spacing convention
is followed as above.</p>
<p>First, let's get the lengths of basic components:</p>
<pre>// Returns the length of the string representation of the number n
constexpr <em>size_t value_length</em>(int <em>n</em>, int bound = 10, size_t digits = 1)
{
return
<em>n &lt; bound ? digits : value_length(n, bound * 10, digits + 1)</em>;
}
// Returns the length of s
constexpr <em>size_t string_length</em>(const char *<em>s</em>, size_t index = 0)
{
return <em>s[index] == '\0' ? index : string_length(s, index + 1)</em>;
}</pre><p>Now, the length of the constant declaration. Here is where we lose information
about initializers. We are going to format the constant declarations like this:</p>
<pre class="comment">Red = 0, Green = 1, Blue = 2
TrueColor = 1, HighColor = 0</pre><p>This is because Better Enums doesn't provide a way to know what the exact
initializer was or whether there even was one &mdash; just the numeric value of
each constant. If we were trying to be clever, we could avoid formatting
initializers for sequential values, but I won't go through this exercise here.</p>
<pre>// Returns the length of the constants portion of the declaration of Enum,
// as described above.
template &lt;<em>typename Enum</em>&gt;
constexpr <em>size_t constants_length</em>(size_t index = 0, size_t accumulator = 0)
{
return
<em>index &gt;= Enum::_size() ? accumulator :
constants_length&lt;Enum&gt;(
index + 1, accumulator
+ string_length(", ")
+ string_length(Enum::_names()[index])
+ string_length(" = ")
+ value_length(
Enum::_values()[index]._to_integral()))</em>;
}</pre><p>Finally, we can combine these to get the length of the formatted declaration of
the whole enum:</p>
<pre>// Returns the length of the whole declaration of Enum, assuming the
// underlying type is int, and the constants are initialized as assumed by
// constants_length() above.
template &lt;<em>typename Enum</em>&gt;
constexpr <em>size_t declaration_length</em>()
{
return
<em>string_length("BETTER_ENUM(")
+ string_length(Enum::_name())
+ string_length(", int")
+ constants_length&lt;Enum&gt;()
+ string_length(")")</em>;
}</pre><a id="FormattingTheEnums"></a><h3>Formatting the enums</h3>
<p>Now, we can declare the buffers. The memory will be reserved at load time by the
binary's loader. The extra one byte in each buffer is for the null terminator.</p>
<pre><em>char</em> channel_definition[<em>declaration_length&lt;Channel&gt;() + 1</em>];
<em>char</em> depth_definition[<em>declaration_length&lt;Depth&gt;() + 1</em>];</pre><p>Let's also create the formatting function. This is executed at run time, but we
will be giving it pointers to our statically-allocated buffers. It will format
the enum declaration and then return the number of bytes it wrote to the buffer,
so that we can do a sanity check on it.</p>
<pre>template &lt;<em>typename Enum</em>&gt;
<em>size_t format</em>(char *<em>buffer</em>)
{
size_t offset = 0;
offset += std::sprintf(buffer, <em>"BETTER_ENUM(%s, int", Enum::_name()</em>);
<em>for</em> (<em>Enum value</em> : <em>Enum::_values()</em>) {
offset +=
std::sprintf(buffer + offset,
<em>", %s = %i",
value._to_string(), value._to_integral()</em>);
}
offset += std::sprintf(buffer + offset, <em>")"</em>);
return <em>offset</em>;
}</pre><a id="CheckingOurWork"></a><h3>Checking our work</h3>
<p>Now, we can write and run this code.</p>
<pre>int main()
{
size_t channel_length = <em>format&lt;Channel&gt;</em>(channel_definition);
assert(channel_length + 1 == sizeof(channel_definition));
size_t depth_length = <em>format&lt;Depth&gt;</em>(depth_definition);
assert(depth_length + 1 == sizeof(depth_definition));
std::cout &lt;&lt; <em>channel_definition</em> &lt;&lt; std::endl;
std::cout &lt;&lt; <em>depth_definition</em> &lt;&lt; std::endl;
return 0;
}</pre><p>It prints:</p>
<pre class="comment">BETTER_ENUM(Channel, int, Red = 0, Green = 1, Blue = 2)
BETTER_ENUM(Depth, int, TrueColor = 1, HighColor = 0)</pre>
<section class="tutorial-footer">
<p class="up">
Return to the <a href="../index.html#CompileTimeDemos">demo index</a>.
</p>
</section>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

220
demo/SpecialValues.html Normal file
View File

@ -0,0 +1,220 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Special values - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/demo/SpecialValues.html" />
<meta name="description" content="An example that uses Better Enums compile-time reflection to
create invalid and default values for each enum, enforced statically by the
compiler, for readability and maintainability." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="../better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="../index.html">Home</a>
<a href="../tutorial/HelloWorld.html">Tutorial</a>
<a href="../ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="../index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<p>
This is an example of code you can write on top of Better Enums. It's a valid
program &mdash; you can <a href="https://github.com/aantron/better-enums/blob/0.11.3/example/101-special-values.cc">download</a> it and try it out. The
program is also part of the test suite.
</p>
<h2>Special values</h2>
<p>Suppose your project has a convention where each enum has special <em>invalid</em> and
<em>default</em> values &mdash; for example, <code>Enum::Invalid</code> is <em>invalid</em>, and the
first valid constant is <em>default</em>. With Better Enums, you can get the compiler
to enforce the convention. At the end of this demo, we will have defined
functions and templates that allow us to write:</p>
<pre class="comment"><em>Channel channel</em> = <em>default_</em>;
<em>Channel channel</em> = <em>invalid</em>;
void do_something(<em>Channel channel</em>);
do_something(<em>default_</em>);
do_something(<em>invalid</em>);</pre><p>The compiler will compute default and invalid values automatically, but the
programmer will also be able to override the choice. Obviously, the syntax above
is very legible and maintainable &mdash; the intent is clear and your code base
will respond automatically to changes in enum definitions.</p>
<p><a id="contents"></a><h3 class="contents">Contents</h3><ul class="contents"><li><a href="#InvalidValues">Invalid values</a></li><li><a href="#DefaultValues">Default values</a></li><li><a href="#MakingTheSyntaxNicer">Making the syntax nicer</a></li></ul></p>
<a id="InvalidValues"></a><h3>Invalid values</h3>
<p>Let's start by defining the invalid values.</p>
<pre>#include &lt;iostream&gt;
#include &lt;stdexcept&gt;
<em>#include &lt;enum.h&gt;</em></pre><p>Perhaps the convention is that the invalid value is usually called <code>Invalid</code>,
but not for all enums. We will encode that using a template function. The
unspecialized version will encode the default policy:</p>
<pre><em>template</em> &lt;<em>typename Enum</em>&gt;
constexpr <em>Enum invalid_impl</em>() { return <em>Enum::Invalid</em>; }</pre><p>A macro allows us to override the invalid value by specializing the template:</p>
<pre><em>#define OVERRIDE_INVALID</em>(<em>Enum</em>, <em>Value</em>) \
template&lt;&gt; \
constexpr <em>Enum invalid_impl</em>&lt;<em>Enum</em>&gt;() { return <em>Enum::Value</em>; }</pre><p>Now, we can declare enums like these:</p>
<pre>BETTER_ENUM(<em>Channel</em>, int, Red, Green, Blue, <em>Invalid</em>)
// Invalid is the invalid value by default
BETTER_ENUM(<em>Compression</em>, int, <em>Undefined</em>, None, Huffman)
OVERRIDE_INVALID(<em>Compression</em>, <em>Undefined</em>)</pre><p>and use them:</p>
<pre>static_assert(<em>invalid_impl</em>&lt;<em>Channel</em>&gt;() == +<em>Channel::Invalid</em>, "");
static_assert(<em>invalid_impl</em>&lt;<em>Compression</em>&gt;() == +<em>Compression::Undefined</em>, "");</pre><p>This even supports enums that don't have an invalid value at all. As long as
they don't have a constant called <code>Invalid</code>, you will get a compile-time error
if you try to call <code>invalid_impl&lt;&gt;()</code> on them &mdash; as you probably should!</p>
<a id="DefaultValues"></a><h3>Default values</h3>
<p>Perhaps here the convention is the first value that is not invalid is default,
unless, again, overridden by the programmer. This can be encoded using only a
slightly more complex template function for the general case:</p>
<pre><em>template</em> &lt;<em>typename Enum</em>&gt;
constexpr <em>Enum default_imp</em>l()
{
return
<em>Enum::_size() &lt; 2 ?
throw std::logic_error("enum has no valid constants") :
Enum::_values()[0] == invalid_impl&lt;Enum&gt;() ?
Enum::_values()[1] :
Enum::_values()[0]</em>;
}</pre><p>The above code gives us the first value if it is not invalid, otherwise the
second value.</p>
<p>The companion macro for overriding the choice of default value is almost the
same as it was for invalid. The difference is that we do an extra sanity check
to make sure the programmer doesn't declare the invalid value to be the default.
If the sanity check fails, we produce a nice error message. Again, we are
assuming that this is dictated by policy.</p>
<pre><em>#define OVERRIDE_DEFAULT</em>(<em>Enum</em>, <em>Value</em>) \
static_assert(<em>Enum::Value</em> != <em>Enum::Invalid</em>, \
<em>#Enum ": default cannot equal invalid"</em>); \
template&lt;&gt; \
constexpr <em>Enum default_impl</em>&lt;<em>Enum</em>&gt;() { return <em>Enum::Value</em>; }</pre><p>And, as before, the usage:</p>
<pre>static_assert(<em>default_impl</em>&lt;<em>Channel</em>&gt;() == +<em>Channel::Red</em>, "");
static_assert(<em>default_impl</em>&lt;<em>Compression</em>&gt;() == +<em>Compression::None</em>, "");</pre><p>And, if you do</p>
<pre>BETTER_ENUM(<em>Answer</em>, int, Yes, No, <em>Invalid</em>)
// OVERRIDE_DEFAULT(<em>Answer</em>, <em>Invalid</em>)</pre><p>you will get a helpful compile-time error saying
<code>Answer: default cannot equal invalid</code>.</p>
<a id="MakingTheSyntaxNicer"></a><h3>Making the syntax nicer</h3>
<p>At this point, our policy is encoded by the ugly-looking functions
<code>invalid_impl</code> and <code>default_impl</code>. We want a nicer syntax. The main reason we
don't just use these functions directly is that the compiler wouldn't infer
their template arguments from the context. For example, we would have to write
things like</p>
<pre class="comment">Channel channel = invalid_impl&lt;Channel&gt;();</pre><p>which is unfortunate, because it results in repetition.</p>
<p>In this section, we introduce two global objects called <code>invalid</code> and <code>default_</code>
that will implicitly convert to any Better Enum type, and provide the invalid
or default value, respectively, when they do so. They will act as new
"keywords".</p>
<pre><em>struct invalid_t</em> {
template &lt;<em>typename To</em>&gt;
constexpr <em>operator To</em>() const { return <em>invalid_impl&lt;To&gt;()</em>; }
};
<em>struct default_t</em> {
template &lt;<em>typename To</em>&gt;
constexpr <em>operator To</em>() const { return <em>default_impl&lt;To&gt;()</em>; }
};
constexpr <em>invalid_t invalid</em>{};
constexpr <em>default_t default_</em>{};</pre><p>As you can see, both of these provide the families of implicit conversions that
we need. Now, we can test:</p>
<pre>static_assert(+<em>Channel::Invalid</em> == <em>invalid</em>, "");
static_assert(+<em>Compression::Undefined</em> == <em>invalid</em>, "");
static_assert(+<em>Channel::Red</em> == <em>default_</em>, "");
static_assert(+<em>Compression::None</em> == <em>default_</em>, "");</pre><p>Finally, we can have nice code such as this:</p>
<pre>void dump(<em>Channel channel</em>)
{
std::cout &lt;&lt; channel._to_string() &lt;&lt; std::endl;
}
int main()
{
dump(<em>invalid</em>);
<em>Channel channel</em> = <em>default_</em>;
dump(channel);
return 0;
}</pre><hr>
<p>There are many possible variations of these policies, but I think most of them
can be encoded in a reasonable fashion using the tools Better Enums provides.
Enjoy!</p>
<section class="tutorial-footer">
<p class="up">
Return to the <a href="../index.html#CompileTimeDemos">demo index</a>.
</p>
</section>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

BIN
image/tweet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
image/twsupport.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

313
index.html Normal file
View File

@ -0,0 +1,313 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Better Enums - Clean reflective enums for C++</title>
<link rel="canonical" href="http://aantron.github.io/better-enums" />
<meta name="description" content="Reflective enums in a single header file, with clean syntax.
The enums can be converted to string, iterated, and counted, at run time or
as part of metaprogramming. Free and open source under the BSD license." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="index">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="index.html">Home</a>
<a href="tutorial/HelloWorld.html">Tutorial</a>
<a href="ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<div class="splash">
<pre class="left">enable
declare
parse
format
count
iterate
switch
safe cast
during
compilation
</pre>
<pre class="right"><em>#include &lt;enum.h&gt;</em>
<em>BETTER_ENUM(Channel, int, Red = 1, Green, Blue)</em>
Channel c = <em>Channel::_from_string("Red")</em>;
const char *s = <em>c._to_string()</em>;
size_t n = <em>Channel::_size()</em>;
<em>for (Channel c : Channel::_values())</em> {
run_some_function(c);
}
<em>switch (c)</em> {
<em>case Channel::Red</em>: // ...
<em>case Channel::Green</em>: // ...
<em>case Channel::Blue</em>: // ...
}
Channel c = <em>Channel::_from_integral(3)</em>;
<em>constexpr</em> Channel c =
<em>Channel::_from_string("Blue")</em>;</pre>
</div>
<p class="splash-text">
<span class="self">Better Enums</span> is a single, lightweight header file that makes your compiler generate
<em>reflective</em> enum types.
</p>
<p>That means you can easily convert enums to and from strings,
validate them, and loop over them. In <span class="cpp">C++</span><span class="eleven">11</span>, you can do it all at
compile time.</p>
<p>It's what built-in enums ought to support. Better Enums simply adds the missing
features. And, it is based on the best known techniques, thoroughly tested,
fast, portable, and documented exhaustively.</p>
<p>To use it, just include <code>enum.h</code> and begin the
<a href="tutorial/HelloWorld.html">tutorial</a>!</p>
<div class="hack"></div>
<a id="Highlights"></a><h3>Highlights</h3>
<ul class="blurbs">
<li class="zero-mod-two zero-mod-three">
<strong>Unobtrusive syntax</strong>
<em>
No ugly macros. Use initializers as with built-in <code>enums</code>.
Internal members have underscores to avoid clashing with your constant
names.
</em>
</li>
<li class="one-mod-two one-mod-three">
<strong>No external dependencies</strong>
<em>
Uses only standard <span class="cpp">C++</span>. Installation is simple &mdash; just download
<code>enum.h</code>. There are no objects or libraries to link with.
</em>
</li>
<li class="zero-mod-two two-mod-three">
<strong>No generator program needed</strong>
<em>
Just include <code>enum.h</code>. It's a metaprogram executed by your
compiler.
</em>
</li>
<li class="one-mod-two zero-mod-three">
<strong>Plays nice with <code>switch</code></strong>
<em>
Use a Better Enum like a built-in <code>enum</code>, and still have the
compiler do case checking.
</em>
</li>
<li class="zero-mod-two one-mod-three">
<strong>Don't repeat yourself</strong>
<em>
No more unmaintanable maps or <code>switch</code> statements for
converting enums to strings.
</em>
</li>
<li class="one-mod-two two-mod-three">
<strong>Non-contiguous sequences</strong>
<em>
Iteration and counting are much easier to maintain than with an extra
<code>Count</code> constant and assuming a dense range.
</em>
</li>
<li class="zero-mod-two zero-mod-three">
<strong>Fast compilation</strong>
<em>
Much less impact on build time than even just including
<code>iostream</code>. <code>enum.h</code> is only slightly more than 1000
lines long.
</em>
</li>
<li class="one-mod-two one-mod-three">
<strong>Compile-time reflection</strong>
<em>
Have the compiler do additional enum processing using your own
templates or <code>constexpr</code> functions.
</em>
</li>
<li class="zero-mod-two two-mod-three">
<strong>Uniform interface for <span class="cpp">C++</span><span class="eleven">98</span>, <span class="cpp">C++</span><span class="eleven">11</span></strong>
<em>
Scoped, sized, reflective enums for <span class="cpp">C++</span><span class="eleven">98</span>, and an easy upgrade
path.
</em>
</li>
<li class="one-mod-two zero-mod-three">
<strong>Stream operators</strong>
<em>
Write enum names directly to <code>std::cout</code> or use
<code>boost::lexical_cast</code>.
</em>
</li>
<li class="zero-mod-two one-mod-three">
<strong>Free and open source</strong>
<em>
Released under the BSD license for use in any project, free or commercial.
</em>
</li>
</ul>
<div class="hack"></div>
<a id="Documentation"></a><h3>Documentation</h3>
<ul class="blurbs resources">
<li class="zero-mod-two zero-mod-three">
<a id="Tutorial"></a>
<strong>Tutorial</strong>
<ol>
<li><a href="tutorial/HelloWorld.html">Hello, World!</a></li>
<li><a href="tutorial/Conversions.html">Conversions</a></li>
<li><a href="tutorial/Iteration.html">Iteration</a></li>
<li><a href="tutorial/SafeSwitch.html">Safe switch</a></li>
<li><a href="tutorial/Maps.html">Maps</a></li>
<li><a href="tutorial/StreamOperators.html">Stream operators</a></li>
<li><a href="tutorial/ScopeAndSafety.html">Scope and safety</a></li>
<li><a href="tutorial/Representation.html">Representation</a></li>
<li><a href="tutorial/CompileTimeUsage.html">Compile-time usage</a></li>
</ol>
</li>
<li class="one-mod-two one-mod-three">
<strong>Reference</strong>
<ul>
<li><a href="ApiReference.html">API reference</a></li>
<li><a href="CompilerSupport.html">Compiler support</a></li>
<li><a href="OptInFeatures.html">Opt-in features</a></li>
<li><a href="ExtendingLimits.html">Extending limits</a></li>
<li><a href="Performance.html">Performance</a></li>
<li>
<a href="DesignDecisionsFAQ.html">Design decisions FAQ</a>
</li>
<li>
<a href="http://www.codeproject.com/Articles/1002895/Clean-Reflective-Enums-Enum-to-String-with-Nice-Sy">
Implementation <span class="external">[CodeProject]</span>
</a>
</li>
</ul>
</li>
<li class="zero-mod-two two-mod-three">
<a id="CompileTimeDemos"></a>
<strong>Advanced</strong>
<ul>
<li><a href="demo/SpecialValues.html">Special values</a></li>
<li><a href="demo/BitSets.html">Bit sets</a></li>
<li><a href="demo/SemiQuine.html">Semi-quine</a></li>
<li><a href="demo/C++17ReflectionProposal.html">C++17 reflection proposal</a></li>
</ul>
</li>
</ul>
<div class="hack"></div>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

64
sitemap.xml Normal file
View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://aantron.github.io/better-enums/tutorial/HelloWorld.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/tutorial/Conversions.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/tutorial/Iteration.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/tutorial/SafeSwitch.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/tutorial/Maps.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/tutorial/StreamOperators.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/tutorial/ScopeAndSafety.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/tutorial/Representation.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/tutorial/CompileTimeUsage.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/demo/SpecialValues.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/demo/BitSets.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/demo/SemiQuine.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/demo/C++17ReflectionProposal.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/ApiReference.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/CompilerSupport.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/DesignDecisionsFAQ.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/ExtendingLimits.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums</loc>
<priority>1.0</priority>
</url>
<url>
<loc>http://aantron.github.io/better-enums/OptInFeatures.html</loc>
</url>
<url>
<loc>http://aantron.github.io/better-enums/Performance.html</loc>
</url>
</urlset>

View File

@ -0,0 +1,148 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Compile-time usage - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/tutorial/CompileTimeUsage.html" />
<meta name="description" content="Better Enums can be used entirely at compile time in C++11. All
conversion functions are available for constexpr functions or templates." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="../better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="../index.html">Home</a>
<a href="../tutorial/HelloWorld.html">Tutorial</a>
<a href="../ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="../index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<p>
Welcome to the Better Enums tutorials! The code in this tutorial forms a
valid program, which you can <a href="https://github.com/aantron/better-enums/blob/0.11.3/example/9-constexpr.cc">download</a> and play with. The
program runs as part of the automated test suite.
</p>
<h2>Compile-time usage</h2>
<p>When used with <span class="cpp">C++</span><span class="eleven">11</span>, Better Enums are generated entirely during compilation.
All the data is available for use by your own <code>constexpr</code> functions. The
examples in <em>this</em> tutorial aren't very useful, but look at the
<a href="../index.html#CompileTimeDemos">demos</a> at the bottom of the main page to
get an idea of what can be done. Here, you will see the basics.</p>
<pre>#include &lt;iostream&gt;
// The reason for this is explained below.
#ifndef BETTER_ENUMS_CONSTEXPR_TO_STRING
#define BETTER_ENUMS_CONSTEXPR_TO_STRING
#endif
<em>#include &lt;enum.h&gt;</em>
<em>BETTER_ENUM</em>(<em>Channel</em>, <em>int</em>, <em>Red</em> = <em>1</em>, <em>Green</em> = <em>2</em>, <em>Blue</em> = <em>3</em>)
<em>constexpr</em> Channel channel = <em>Channel::_from_integral(2)</em>;
<em>constexpr</em> int value = <em>channel._to_integral()</em>;
<em>constexpr</em> const char *name = <em>channel._to_string()</em>;
<em>constexpr</em> Channel parsed = <em>Channel::_from_string("Red")</em>;</pre><p>All of the above are computed during compilation. The reason for the macro
definition at the top of the file is explained on the
<a href="../OptInFeatures.html#CompileTimeNameTrimming">opt-in features page</a>.
Basically, it makes <code>_to_string</code> <code>constexpr</code>, but slows down compilation.</p>
<p>You can also do things such as:</p>
<pre><em>constexpr size_t length</em>(<em>const char *s</em>, <em>size_t index = 0</em>)
{
return <em>s[index] == '\0'</em> ? <em>index</em> : <em>length(s, index + 1)</em>;
}
<em>constexpr</em> size_t <em>length_of_name_of_second_constant</em> =
<em>length(Channel::_names()[1])</em>;
int main()
{
std::cout &lt;&lt; <em>length_of_name_of_second_constant</em> &lt;&lt; std::endl;
return 0;
}</pre><p>Which prints "5", the length of "Green". That 5 was also computed during
compilation.</p>
<section class="tutorial-footer">
<p class="up">
This is the last tutorial! Return to the
<a href="../index.html">main page</a> for other resources.
</p>
</section>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

211
tutorial/Conversions.html Normal file
View File

@ -0,0 +1,211 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Conversions - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/tutorial/Conversions.html" />
<meta name="description" content="Better Enums conversion functions. Converting to string, from
string, to int, from int, and validation, both case-sensitive and
case-insensitive. Exception-throwing and non-throwing variants presented." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="../better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="../index.html">Home</a>
<a href="../tutorial/HelloWorld.html">Tutorial</a>
<a href="../ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="../index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<p>
Welcome to the Better Enums tutorials! The code in this tutorial forms a
valid program, which you can <a href="https://github.com/aantron/better-enums/blob/0.11.3/example/2-conversions.cc">download</a> and play with. The
program runs as part of the automated test suite.
</p>
<h2>Conversions</h2>
<p>Let's begin by including <code>enum.h</code> and declaring our enum:</p>
<pre>#include &lt;cassert&gt;
#include &lt;iostream&gt;
<em>#include &lt;enum.h&gt;</em>
<em>BETTER_ENUM</em>(<em>Channel</em>, <em>int</em>, <em>Cyan</em> = <em>1</em>, <em>Magenta</em>, <em>Yellow</em>, <em>Black</em>)</pre><p>We now have an <code>int</code>-sized enum with four constants.</p>
<p>There are three groups of conversion functions: for strings, case-insensitive
strings, and integers. They all follow the same pattern, so I'll explain the
string functions in detail, and the rest can be understood by analogy.</p>
<p><a id="contents"></a><h3 class="contents">Contents</h3><ul class="contents"><li><a href="#Strings">Strings</a></li><li><a href="#CaseInsensitiveStrings">Case-insensitive strings</a></li><li><a href="#Integers">Integers</a></li><li><a href="#ValidityChecking">Validity checking</a></li></ul></p>
<a id="Strings"></a><h3>Strings</h3>
<p>There are three functions:</p>
<ol>
<li><code>._to_string</code></li>
<li><code>::_from_string</code></li>
<li><code>::_from_string_nothrow</code></li>
</ol>
<pre>int main()
{
<em>Channel channel = Channel::Cyan</em>;
std::cout &lt;&lt; <em>channel._to_string()</em> &lt;&lt; " ";</pre><p>As you'd expect, the code above prints "Cyan".</p>
<p>If <code>channel</code> is invalid &mdash; for example, if you simply cast the number "42"
to <code>Channel</code> &mdash; then the result of <code>to_string</code> is undefined.</p>
<hr>
<pre> channel = <em>Channel::_from_string("Magenta")</em>;
std::cout &lt;&lt; channel._to_string() &lt;&lt; " ";</pre><p>This is also straightforward. If you pass a string which is not the name of a
declared value, <code>_from_string</code> throws <code>std::runtime_error</code>.</p>
<hr>
<p>If you don't want an exception, there is <code>_from_string_nothrow</code>:</p>
<pre> <em>better_enums::optional&lt;Channel&gt;</em> maybe_channel =
<em>Channel::_from_string_nothrow("Yellow")</em>;
if (<em>!maybe_channel</em>)
std::cout &lt;&lt; "error";
else
std::cout &lt;&lt; <em>maybe_channel-&gt;</em>_to_string() &lt;&lt; " ";</pre><p>This returns an <em>optional value</em>, in the style of
<a href="http://www.boost.org/doc/libs/1_58_0/libs/optional/doc/html/index.html"><code>boost::optional</code></a>
or the proposed
<a href="http://en.cppreference.com/w/cpp/experimental/optional"><code>std::optional</code></a>.</p>
<p>What that means for the above code is:</p>
<ul>
<li>if the conversion succeeds, <code>maybe_channel</code> converts to <code>true</code> and
<code>*maybe_channel</code> is the converted value of type <code>Channel</code>,</li>
<li>if the conversion fails, <code>maybe_channel</code> converts to <code>false</code>.</li>
</ul>
<p>In <span class="cpp">C++</span><span class="eleven">11</span>, you can use <code>auto</code> to avoid writing out the optional type:</p>
<pre class="comment"> <em>auto</em> maybe_channel = <em>Channel::_from_string_nothrow("Yellow")</em>;
if (<em>!maybe_channel</em>)
std::cout &lt;&lt; "error";
else
std::cout &lt;&lt; <em>maybe_channel-&gt;</em>_to_string() &lt;&lt; " ";</pre><a id="CaseInsensitiveStrings"></a><h3>Case-insensitive strings</h3>
<p>The "<code>_nocase</code>" string conversions follow the same pattern, except for the lack
of a "<code>to_string_nocase</code>".</p>
<ol>
<li><code>::_from_string_nocase</code></li>
<li><code>::_from_string_nocase_nothrow</code></li>
</ol>
<pre> channel = <em>Channel::_from_string_nocase("cYaN")</em>;
std::cout &lt;&lt; channel._to_string() &lt;&lt; " ";
maybe_channel = <em>Channel::_from_string_nocase_nothrow("rEeD")</em>;
assert(!maybe_channel);</pre><a id="Integers"></a><h3>Integers</h3>
<p>And, it is similar with the <em>representation type</em> <code>int</code>:</p>
<ol>
<li><code>._to_integral</code></li>
<li><code>::_from_integral</code></li>
<li><code>::_from_integral_nothrow</code></li>
<li><code>::_from_integral_unchecked</code></li>
</ol>
<pre> channel = Channel::Cyan;
std::cout &lt;&lt; <em>channel._to_integral()</em> &lt;&lt; " ";
channel = <em>Channel::_from_integral(2)</em>;
std::cout &lt;&lt; channel._to_string() &lt;&lt; " ";
maybe_channel = <em>Channel::_from_integral_nothrow(0)</em>;
assert(<em>!maybe_channel</em>);</pre><p>That prints "1 Magenta".</p>
<p><code>_from_integral_unchecked</code> is a no-op unchecked cast of integers to enums, so
use it carefully.</p>
<pre> channel = <em>Channel::_from_integral_unchecked(0)</em>;
// <em>Invalid</em> - better not to try converting it to string!</pre><a id="ValidityChecking"></a><h3>Validity checking</h3>
<p>For completeness, Better Enums also provides three validity checking functions,
one for each of the groups of conversions &mdash; string, case-insensitive
string, and integer:</p>
<pre> assert(<em>Channel::_is_valid(3)</em>);
assert(<em>Channel::_is_valid("Magenta")</em>);
assert(<em>Channel::_is_valid_nocase("cYaN")</em>);</pre><hr>
<p>Almost done.</p>
<p>There is one unfortunate wrinkle. You cannot convert a literal constant such as
<code>Channel::Cyan</code> directly to, for example, a string. You have to prefix it with
<code>+</code>:</p>
<pre> std::cout &lt;&lt; (<em>+Channel::Cyan</em>)._to_string();</pre><p>This is due to some type gymnastics in the implementation of Better Enums. The
reference has a
<a href="../ApiReference.html#HelperFunctionsAndTypes">full explanation</a>.</p>
<hr>
<pre> std::cout &lt;&lt; std::endl;
return 0;
}</pre>
<section class="tutorial-footer">
<p class="next">
Continue to the next tutorial: <a href="../tutorial/Iteration.html">Iteration</a>
</p>
<p class="up">
Or, return to the
<a href="../index.html#Tutorial">tutorial index</a>.
</p>
</section>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

128
tutorial/HelloWorld.html Normal file
View File

@ -0,0 +1,128 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Hello, World! - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/tutorial/HelloWorld.html" />
<meta name="description" content="Introductory Better Enums tutorial - a simple, but complete,
Hello World program." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="../better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="../index.html">Home</a>
<a href="../tutorial/HelloWorld.html">Tutorial</a>
<a href="../ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="../index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<p>
Welcome to the Better Enums tutorials! The code in this tutorial forms a
valid program, which you can <a href="https://github.com/aantron/better-enums/blob/0.11.3/example/1-hello-world.cc">download</a> and play with. The
program runs as part of the automated test suite.
</p>
<h2>Hello, World!</h2>
<p>Download <a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download><code>enum.h</code></a>, then compile this program:</p>
<pre>#include &lt;iostream&gt;
<em>#include "enum.h"</em>
<em>BETTER_ENUM</em>(<em>Word</em>, <em>int</em>, <em>Hello</em>, <em>World</em>)
int main()
{
std::cout &lt;&lt; <em>(+Word::Hello)._to_string()</em> &lt;&lt; ", "
&lt;&lt; <em>(+Word::World)._to_string()</em> &lt;&lt; "!"
&lt;&lt; std::endl;
return 0;
}</pre><p>Run it, and you should see the output "Hello, World!"</p>
<p>Congratulations, you have just created your first Better Enum!</p>
<section class="tutorial-footer">
<p class="next">
Continue to the next tutorial: <a href="../tutorial/Conversions.html">Conversions</a>
</p>
<p class="up">
Or, return to the
<a href="../index.html#Tutorial">tutorial index</a>.
</p>
</section>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

142
tutorial/Iteration.html Normal file
View File

@ -0,0 +1,142 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Iteration - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/tutorial/Iteration.html" />
<meta name="description" content="Using Better Enums to iterate over all the constants of an
enum, as well as over its names. Also shows the same with C++11 for-each syntax." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="../better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="../index.html">Home</a>
<a href="../tutorial/HelloWorld.html">Tutorial</a>
<a href="../ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="../index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<p>
Welcome to the Better Enums tutorials! The code in this tutorial forms a
valid program, which you can <a href="https://github.com/aantron/better-enums/blob/0.11.3/example/3-iterate.cc">download</a> and play with. The
program runs as part of the automated test suite.
</p>
<h2>Iteration</h2>
<p>Better Enums makes it easy to iterate over the values you have declared. For
example, this:</p>
<pre>#include &lt;iostream&gt;
#include &lt;enum.h&gt;
<em>BETTER_ENUM(Channel, int, Red, Green = 2, Blue)</em>
int main()
{
<em>for</em> (<em>size_t index = 0</em>; <em>index &lt; Channel::_size()</em>; <em>++index</em>) {
Channel channel = <em>Channel::_values()[index]</em>;
std::cout &lt;&lt; channel._to_integral() &lt;&lt; " ";
}
std::cout &lt;&lt; std::endl;</pre><p>will print "0 2 3". And this:</p>
<pre> <em>for</em> (<em>size_t index = 0</em>; <em>index &lt; Channel::_size()</em>; <em>++index</em>) {
const char *name = <em>Channel::_names()[index]</em>;
std::cout &lt;&lt; name &lt;&lt; " ";
}
std::cout &lt;&lt; std::endl;</pre><p>will print "Red Green Blue".</p>
<hr>
<p>If you are using <span class="cpp">C++</span><span class="eleven">11</span>, you can have much nicer syntax:</p>
<pre class="comment"> <em>for (Channel channel : Channel::_values())</em>
std::cout &lt;&lt; <em>channel._to_integral()</em> &lt;&lt; " ";
std::cout &lt;&lt; std::endl;
<em>for (const char *name : Channel::_names())</em>
std::cout &lt;&lt; <em>name</em> &lt;&lt; " ";
std::cout &lt;&lt; std::endl;</pre><hr>
<pre> return 0;
}</pre>
<section class="tutorial-footer">
<p class="next">
Continue to the next tutorial: <a href="../tutorial/SafeSwitch.html">Safe switch</a>
</p>
<p class="up">
Or, return to the
<a href="../index.html#Tutorial">tutorial index</a>.
</p>
</section>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

162
tutorial/Maps.html Normal file
View File

@ -0,0 +1,162 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Maps - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/tutorial/Maps.html" />
<meta name="description" content="Mapping enums to arbitrary types and vice versa." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="../better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="../index.html">Home</a>
<a href="../tutorial/HelloWorld.html">Tutorial</a>
<a href="../ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="../index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<p>
Welcome to the Better Enums tutorials! The code in this tutorial forms a
valid program, which you can <a href="https://github.com/aantron/better-enums/blob/0.11.3/example/5-map.cc">download</a> and play with. The
program runs as part of the automated test suite.
</p>
<h2>Maps</h2>
<p>It is possible to create <code>constexpr</code> bidirectional maps between Better Enums and
any type. This is currently an experimental feature. Feedback is very much
wanted, but please don't build any mission-critical code on top of this :)</p>
<p>The way it works is you give Better Enums a function &mdash; say,
<code>const char* describe(Channel)</code>. The library enumerates it to make a map.</p>
<p>The reason for using a function is that a <code>switch</code> statement is, I believe, the
only place where a compiler will check for exhaustiveness. If you forget to
create a case for one of the enum's constants, the compiler can let you know.
Obviously, a <code>switch</code> statement is not data, and needs to be inside a function.
It can only be inside a <code>constexpr</code> function in <span class="cpp">C++</span><span class="eleven">14</span>, so this feature is most
natural in <span class="cpp">C++</span><span class="eleven">14</span>. When you pass the function to Better Enums, the library can
build up a lookup data structure at compile time.</p>
<p>Actually, right now, Better Enums doesn't quite do that &mdash; it enumerates
the function <em>every</em> time you want to convert to an enum (but not <em>from</em> an
enum). It simply does a linear scan every time. This is because I haven't yet
found a data structure whose compile-time generation is fast enough for
practical use.</p>
<hr>
<pre>#include &lt;iostream&gt;
<em>#include</em> &lt;<em>enum.h</em>&gt;
<em>BETTER_ENUM</em>(<em>Channel</em>, <em>int</em>, <em>Red</em>, <em>Green</em>, <em>Blue</em>)</pre><p>We will create a map from this function:</p>
<pre>constexpr <em>const char* describe</em>(<em>Channel channel</em>)
{
switch(<em>channel</em>) {
case <em>Channel::Red</em>: return <em>"the red channel"</em>;
case <em>Channel::Green</em>: return <em>"the green channel"</em>;
case <em>Channel::Blue</em>: return <em>"the blue channel"</em>;
}
return "needed for gcc 5";
}</pre><p>Here is the map. The actual type is <code>better_enums::map&lt;Channel, const char*&gt;</code>.</p>
<pre>constexpr auto <em>descriptions</em> = <em>better_enums::make_map</em>(<em>describe</em>);</pre><p>And the usage:</p>
<pre>int main()
{
std::cout &lt;&lt; <em>descriptions[Channel::Red]</em> &lt;&lt; std::endl;
std::cout &lt;&lt; <em>descriptions</em>.<em>from_enum</em>(<em>Channel::Red</em>) &lt;&lt; std::endl;
std::cout &lt;&lt; <em>descriptions</em>.<em>to_enum</em>(<em>"the green channel"</em>) &lt;&lt; std::endl;
auto <em>not_a_literal</em> = <em>std::string</em>(<em>"the blue channel"</em>);
std::cout &lt;&lt; <em>descriptions</em>.<em>to_enum</em>(<em>not_a_literal</em>.<em>c_str()</em>) &lt;&lt; std::endl;
return 0;
}</pre><hr>
<p><code>make_map</code> above produces a value of type <code>better_enums::map&lt;E, T&gt;</code>. The full
signature of the template <code>better_enums::map</code> is</p>
<pre class="comment"><em>template &lt;typename Enum, typename T, typename Compare = map_compare&lt;T&gt;&gt;</em></pre><p><code>Compare</code> has to be a class with a static member function
<code>bool less(const T&amp;, const T&amp;)</code>. The default implementation
<code>better_enums::map_compare</code> simply applies <code>operator &lt;</code>, except when <code>T</code> is
<code>const char*</code> or <code>const wchar_t*</code>. In that case, it does lexicographic comparison.</p>
<section class="tutorial-footer">
<p class="next">
Continue to the next tutorial: <a href="../tutorial/StreamOperators.html">Stream operators</a>
</p>
<p class="up">
Or, return to the
<a href="../index.html#Tutorial">tutorial index</a>.
</p>
</section>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

View File

@ -0,0 +1,168 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Representation - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/tutorial/Representation.html" />
<meta name="description" content="The underlying memory representation of a Better Enum,
including size and alignment." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="../better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="../index.html">Home</a>
<a href="../tutorial/HelloWorld.html">Tutorial</a>
<a href="../ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="../index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<p>
Welcome to the Better Enums tutorials! The code in this tutorial forms a
valid program, which you can <a href="https://github.com/aantron/better-enums/blob/0.11.3/example/8-representation.cc">download</a> and play with. The
program runs as part of the automated test suite.
</p>
<h2>Representation</h2>
<p>Let's go over some of the low-level properties of a Better Enum. This time, we
will declare a more unusual enum than the ones we have seen.</p>
<pre>#include &lt;cassert&gt;
#include &lt;iostream&gt;
<em>#include &lt;enum.h&gt;</em>
<em>BETTER_ENUM</em>(<em>ContentType</em>, <em>short</em>,
<em>CompressedVideo</em> = <em>5</em>, <em>PCM</em> = <em>8</em>, <em>Subtitles</em> = <em>17</em>, <em>Comment</em> = <em>44</em>)</pre><p>This is for a hypothetical multimedia container file format. Perhaps the files
have sections, and each one has a header:</p>
<pre><em>struct Header</em> {
<em>ContentType type</em>;
short flags;
int offset;
};</pre><hr>
<p>Here is what we have.</p>
<pre>int main()
{
assert(<em>sizeof(ContentType)</em> == <em>2</em>);</pre><p><code>ContentType</code> behaves just like a <code>short</code><sup class="footnote-ref" id="fnref-*"><a href="#fn-*" rel="footnote">1</a></sup>, in fact it simply wraps one. This
makes it possible to lay out structures in a predictable fashion:</p>
<pre> Header <em>header</em> = {ContentType::PCM, 0, 0};
assert(<em>sizeof(header)</em> == <em>8</em>);
assert((size_t)&amp;<em>header.flags -</em> (size_t)&amp;<em>header.type</em> == <em>2</em>);</pre><hr>
<p><code>uint16_t</code> is called <code>ContentType</code>'s <em>underlying</em> or <em>representation</em> type. If
you want to know the representation type of any enum you have declared, it is
available as the member type <code>::_integral</code>:</p>
<pre> <em>ContentType::_integral</em> untrusted_value = 44;</pre><p>Use this if you want a sized field to receive untrusted data, but aren't willing
to call it <code>ContentType</code> yet because you have not validated it. Your validator
will likely call <code>::_from_integral_nothrow</code>, perform any other validation your
application requires, and then return <code>ContentType</code>.</p>
<pre> ContentType type =
ContentType::_from_integral(untrusted_value);
std::cout &lt;&lt; type._to_string() &lt;&lt; std::endl;</pre><hr>
<p>You have probably noticed the initializers on each of the constants in
<code>ContentType</code>. This allows you to declare sparse enums for compatibility with
external protocols or previous versions of your software. The initializers don't
need to be literal integers &mdash; they can be anything that the compiler would
accept in a normal <code>enum</code> declaration. If there was a macro called
<code>BIG_FAT_MACRO</code> declared above, we could have written
<code>Subtitles = BIG_FAT_MACRO</code>. We could also have written
<code>Subtitles = CompressedVideo</code>.</p>
<hr>
<p>The in-memory representation of an enum value is simply the number it has been
assigned by the compiler. You should be safe passing enums to functions like
<code>fread</code> and <code>fwrite</code>, and casting memory blocks known to be safe to <code>struct</code>
types containg enums. The enums will behave as expected.</p>
<hr>
<pre> return 0;
}</pre><div class="footnotes">
<hr>
<ol><li id="fn-*"><p>It should properly be a <code>uint16_t</code>, and the rest of the header fields
should also be explicitly sized. However, this code is trying to be
compatible with <span class="cpp">C++</span><span class="eleven">98</span>, where those names aren't available in a portable
manner.<a href="#fnref-*" rev="footnote">&#8617;</a></p></li>
</ol>
</div>
<section class="tutorial-footer">
<p class="next">
Continue to the next tutorial: <a href="../tutorial/CompileTimeUsage.html">Compile-time usage</a>
</p>
<p class="up">
Or, return to the
<a href="../index.html#Tutorial">tutorial index</a>.
</p>
</section>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

134
tutorial/SafeSwitch.html Normal file
View File

@ -0,0 +1,134 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Safe switch - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/tutorial/SafeSwitch.html" />
<meta name="description" content="Better Enums can be used directly in switch statements like
normal enums, making it possible for the compiler to check that all cases are
listed, increasing the safety of your code." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="../better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="../index.html">Home</a>
<a href="../tutorial/HelloWorld.html">Tutorial</a>
<a href="../ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="../index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<p>
Welcome to the Better Enums tutorials! The code in this tutorial forms a
valid program, which you can <a href="https://github.com/aantron/better-enums/blob/0.11.3/example/4-switch.cc">download</a> and play with. The
program runs as part of the automated test suite.
</p>
<h2>Safe switch</h2>
<p>A Better Enum can be used directly in a <code>switch</code> statement:</p>
<pre>#include &lt;iostream&gt;
<em>#include &lt;enum.h&gt;</em>
<em>BETTER_ENUM(Channel, int, Red, Green, Blue)</em>
int main()
{
Channel channel = Channel::Green;
int n;
<em>switch </em>(<em>channel</em>) {
<em>case Channel::Red</em>: n = 13; break;
<em>case Channel::Green</em>: n = 37; break;
<em>case Channel::Blue</em>: n = 42; break;
}</pre><p>If you miss a case or add a redundant one, your compiler should be able to give
you a warning &mdash; try it!</p>
<p>Note that on msvc, you may need to enable <a href="https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-4-c4062">warning C4062</a>.</p>
<hr>
<pre> std::cout &lt;&lt; n &lt;&lt; std::endl;
return 0;
}</pre>
<section class="tutorial-footer">
<p class="next">
Continue to the next tutorial: <a href="../tutorial/Maps.html">Maps</a>
</p>
<p class="up">
Or, return to the
<a href="../index.html#Tutorial">tutorial index</a>.
</p>
</section>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

View File

@ -0,0 +1,155 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Scope and safety - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/tutorial/ScopeAndSafety.html" />
<meta name="description" content="Better Enums type safety features and limitations." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="../better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="../index.html">Home</a>
<a href="../tutorial/HelloWorld.html">Tutorial</a>
<a href="../ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="../index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<p>
Welcome to the Better Enums tutorials! The code in this tutorial forms a
valid program, which you can <a href="https://github.com/aantron/better-enums/blob/0.11.3/example/7-safety.cc">download</a> and play with. The
program runs as part of the automated test suite.
</p>
<h2>Scope and safety</h2>
<p>This tutorial shows some of the safety features of Better Enums: scope, how to
control conversions, and the lack of a default constructor.</p>
<p>On balance, Better Enums are in one way less type-safe than enum class, and in
another way more type-safe. The first difference in safety is the presence of
implicit conversion to integral types. The second difference is the lack of a
default constructor. Both of these can be toggled, so you can make Better Enums
strictly safer than enum class, or just as safe.</p>
<p><a id="contents"></a><h3 class="contents">Contents</h3><ul class="contents"><li><a href="#Scope">Scope</a></li><li><a href="#ImplicitConversion">Implicit conversion</a></li><li><a href="#DefaultConstructor">Default constructor</a></li></ul></p>
<a id="Scope"></a><h3>Scope</h3>
<p>You have probably noticed by now that Better Enums are scoped: when you declare</p>
<pre>#include &lt;cassert&gt;
<em>#include &lt;enum.h&gt;</em>
<em>BETTER_ENUM</em>(<em>Channel</em>, <em>int</em>, <em>Red</em> = <em>1</em>, <em>Green</em>, <em>Blue</em>)</pre><p>you don't get names such as <code>Red</code> in the global namespace. Instead, you get
<code>Channel</code>, and <code>Red</code> is accessible as <code>Channel::Red</code>. This is no big deal in
<span class="cpp">C++</span><span class="eleven">11</span>, which has <code>enum class</code>. In <span class="cpp">C++</span><span class="eleven">98</span>, however, this typically requires
effort. Better Enums brings scope uniformly to both variants. So, despite the
above declaration, you can safely declare</p>
<pre><em>BETTER_ENUM</em>(<em>Node</em>, <em>char</em>, <em>Red</em>, <em>Black</em>)</pre><p>and everything will work as expected.</p>
<pre>int main()
{
assert((+<em>Channel::Red</em>)._to_integral() <em>!=</em> (+<em>Node::Red</em>)._to_integral());</pre><a id="ImplicitConversion"></a><h3>Implicit conversion</h3>
<p>A major complaint in <span class="cpp">C++</span><span class="eleven">98</span> is that <code>enums</code> are implicitly convertible to
integers. Unfortunately, that is also true of Better Enums, and I haven't found
a way to forbid the conversions and still have switch case checking.</p>
<p>Better Enums can be made as safe as <code>enum class</code> in <span class="cpp">C++</span><span class="eleven">11</span>, however. If your
compiler supports <code>enum class</code> and you define
<code>BETTER_ENUMS_STRICT_CONVERSION</code> before including <code>enum.h</code>, the following code
will not compile:</p>
<pre class="comment"> Channel channel = Channel::Red;
int n = channel;</pre><p>The reason this is not enabled by default is explained in the reference page on
<a href="../OptInFeatures.html#StrictConversions">strict conversions</a>.</p>
<p>You can conveniently define the macro on your compiler's command line, or by
creating a little header file that defines it, and then includes
<code>enum.h</code>. You can then include this new header file in your project
everywhere where you would have included <code>enum.h</code>.</p>
<a id="DefaultConstructor"></a><h3>Default constructor</h3>
<p>Better Enums generate without a default constructor. The purpose is to support
the convention where if a Better Enum exists, then it has a valid value. So, if
you uncomment this code, the program won't compile:</p>
<pre class="comment"> Channel channel;</pre><p>If this is too strict for your project, you can relax it as described
<a href="../OptInFeatures.html#DefaultConstructors">here</a>.</p>
<hr>
<pre> return 0;
}</pre>
<section class="tutorial-footer">
<p class="next">
Continue to the next tutorial: <a href="../tutorial/Representation.html">Representation</a>
</p>
<p class="up">
Or, return to the
<a href="../index.html#Tutorial">tutorial index</a>.
</p>
</section>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>

View File

@ -0,0 +1,131 @@
<!-- Generated automatically - edit the templates! -->
<!DOCTYPE html>
<html>
<head>
<title>Stream operators - Better Enums</title>
<link rel="canonical" href="http://aantron.github.io/better-enums/tutorial/StreamOperators.html" />
<meta name="description" content="Using Better Enums with stream input and output operators." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="../better-enums.css" />
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-62962513-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body class="">
<nav>
<div class="container">
<a class="first" href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download</a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
<a href="../index.html">Home</a>
<a href="../tutorial/HelloWorld.html">Tutorial</a>
<a href="../ApiReference.html">Reference</a>
</div>
</nav>
<div class="spacer">&nbsp;</div>
<header>
<div class="container">
<section>
<h1><a href="../index.html">Better Enums</a></h1>
<h2>Reflective compile-time enums for <span class="cpp">C++</span></h2>
<h3>Open-source under the BSD license</h3>
</section>
<section class="notes">
<p>Version 0.11.3</p>
<p>To install, just add <code>enum.h</code> to your project.</p>
<p>
Visit the GitHub repo for issues, feedback, and the latest development.
</p>
</section>
<section class="buttons">
<a href="https://raw.githubusercontent.com/aantron/better-enums/0.11.3/enum.h"
download>Download <code>enum.h</code></a>
<a href="https://github.com/aantron/better-enums">GitHub</a>
</section>
</div>
</header>
<div class="main">
<div class="container">
<p>
Welcome to the Better Enums tutorials! The code in this tutorial forms a
valid program, which you can <a href="https://github.com/aantron/better-enums/blob/0.11.3/example/6-iostreams.cc">download</a> and play with. The
program runs as part of the automated test suite.
</p>
<h2>Stream operators</h2>
<p>These work <em>almost</em> as you'd expect. First, make sure you include <code>iostream</code>
before <code>enum.h</code> in any translation unit in which you intend to use the
operators:</p>
<pre>#include &lt;iostream&gt;
#include &lt;enum.h&gt;
<em>BETTER_ENUM(Channel, int, Red, Green, Blue)</em>
int main()
{
std::cout &lt;&lt; <em>+Channel::Red</em> &lt;&lt; std::endl;
return 0;
}</pre><p>The thing to watch for is the <code>+</code>: without it, <code>Channel::Red</code> is a value of type
<code>Channel::_enumerated</code>, a <span class="cpp">C++</span><span class="eleven">98</span> enum type, so writing that to <code>cout</code> will
output an integer. <code>+Channel::Red</code>, however, is a value of type <code>Channel</code>, and
writing <em>that</em> instead will output the string <code>"Red"</code>.</p>
<p>Input is also supported:</p>
<pre class="comment">Channel channel = Channel::Blue;
std::cin &gt;&gt; channel; // Expects input such as "Green".</pre><hr>
<p>Only <code>char</code> streams are supported for the time being.</p>
<section class="tutorial-footer">
<p class="next">
Continue to the next tutorial: <a href="../tutorial/ScopeAndSafety.html">Scope and safety</a>
</p>
<p class="up">
Or, return to the
<a href="../index.html#Tutorial">tutorial index</a>.
</p>
</section>
</div>
</div>
<footer>
<div class="container">
Copyright &copy; 2015-2019 Anton Bachin. Released under the BSD 2-clause
license. See
<a href="https://github.com/aantron/better-enums/blob/0.11.3/doc/LICENSE">
LICENSE</a>.
<br />
This page is part of the documentation for Better Enums 0.11.3.
</div>
</footer>
</body>
</html>