Initial release.

This commit is contained in:
Anton Bachin 2015-05-11 16:44:37 -04:00
parent f54960590a
commit dd606fd450
28 changed files with 3275 additions and 0 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
*.h linguist-language=C++

3
.gitignore vendored
View File

@ -1,2 +1,5 @@
*.pyc
*.exe
scratch/
doc-publish/
test/*.cc

23
LICENSE Normal file
View File

@ -0,0 +1,23 @@
Copyright (c) 2012-2015, Anton Bachin
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

112
README.md Normal file
View File

@ -0,0 +1,112 @@
# Better Enums
Generator-free reflective C++11 enum library with clean syntax. For example:
ENUM(Channel, int, Red = 1, Green, Blue);
defines a type `Channel`. You can then do natural things like:
Channel channel = Channel::Green;
channel.to_string(); // Results in the string "Green"
channel.to_integral(); // Results in the integer 2
Channel::_from_string("Red"); // Results in Channel::Red
Channel::_from_int(3) // Results in Channel::Blue
for (Channel channel : Channel::_values) {
// Iterate over all channels
}
...and more. See the
[examples](https://github.com/aantron/better-enums/tree/master/example) for a
tutorial.
## Installation
Simply add `enum.h` and `enum_preprocessor_map.h` to your project. The current
version can be found at
[https://github.com/aantron/better-enums](https://github.com/aantron/better-enums).
`enum_preprocessor_map.h` can handle enums with up to 256 constants. If you have
more, re-generate it by running something like:
./pp_map_gen.py enum_preprocessor_map.h 512
This only needs to be done once when the constant limit is exceeded. You don't
need to do this on every build. I hope to remove the need for this completely in
a future version.
## Features
- Generated at compile time by `constexpr` functions and the preprocessor.
`pp_map_gen.py` is only needed if you have an enum with more than 256
constants.
- Safe conversions between enums and integers and strings.
[1-basic.cc](https://github.com/aantron/better-enums/blob/master/example/1-basic.cc)
- Iterable collections of constants and names.
[2-iterate.cc](https://github.com/aantron/better-enums/blob/master/example/2-iterate.cc)
- Range information, such as the number of constants defined and the maximum
constant.
[2-iterate.cc](https://github.com/aantron/better-enums/blob/master/example/2-iterate.cc)
- Switch case checking.
[3-switch.cc](https://github.com/aantron/better-enums/blob/master/example/3-switch.cc)
- Almost all operations are `constexpr` and can be used at compile time in your
own `constexpr` code.
[4-constexpr.cc](https://github.com/aantron/better-enums/blob/master/example/4-constexpr.cc)
- Constant values can be set (`Red = 1`) and aliased (`Favorite = Green`), just
like with built-in enums.
- Generating a large number of enums is faster than including a typical standard
header like `iostream` performance test included.
- Explicit choice of underlying representation type.
- Header-only.
- No dependencies besides the standard library.
- Tested on gcc 4.9 and clang 3.6.
The library compiles only with gcc and clang due to use of weak symbols and due
to lagging C++11 support in msvc. It should ultimately be portable to msvc,
since msvc has its own version of weak symbols. Everything else in the library
is standard C++.
## Explanation
The `ENUM` macro specializes a template based around a regular `enum`
declaration, though it is more similar to `enum class` in the degree of type
safety. The following are spiritually equivalent:
ENUM(Channel, int, Red = 1, Green, Blue);
enum class Channel : int {Red = 1, Green, Blue};
ENUM(Depth, char, Indexed8Bit, HighColor, TrueColor);
enum class Depth : char {Indexed8Bit, HighColor, TrueColor};
See the full [documentation](http://aantron.github.io/better-enums).
## Development plan
There are several areas that still need improvement.
- I will try to eliminate the need for `pp_map_gen.py`. The library will then
consist of one file, `enum.h`.
- `to_string` can be made `constexpr`, like most of the rest of the code.
- Iterators over defined constants should be made random-access. This would
allow `constexpr` functions to use them by adding 1 the only way to advance
them now is by mutating increment.
- Some enum types might have a sensible choice for a default constructor. The
library should allow it to be customized.
- All safety checks are currently done by linear scans. This may be a
performance problem for enum types with many constants.
- Better diagnostics for empty enums or too many constants.
- Conversions from integers and strings that don't throw exceptions, but
indicate failure by some other means.
## License
Better Enums is released under the BSD 2-clause license. See
[LICENSE](https://github.com/aantron/better-enums/blob/master/LICENSE).
## History
The library was originally developed by the author in the winter of 2012-2013 at
Hudson River Trading, as a replacement for an older generator called
`BETTER_ENUM`.

940
doc/index.html Normal file
View File

@ -0,0 +1,940 @@
<!DOCTYPE html>
<html>
<head>
<link rel="canonical" href="http://aantron.github.io/better-enums" />
<title>Better Enums - No-Generator C++ Enums with String Conversions</title>
<meta name="description" content="Reference documentation and links to code and
tutorial for Better Enums, a no-generator compile-time C++11 enum library
with concise syntax and a high degree of type safety. Better Enums is
reflective: it provides string conversions, iteration over declared
constants, and range information. Most members are constexpr, so they can be
used in your own compile-time code. The library depends only on the standard
library and is header-only. It is almost entirely standard C++." />
<meta name="author" content="Anton Bachin" />
<meta name="viewport" content="width=device-width" />
<style>
body {
margin: 0;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 16px;
}
header {
position: fixed;
top: 0;
z-index: 1;
width: 100%;
padding: 0 3em;
background-color: black;
color: white;
}
h1, h2 {
letter-spacing: -1px;
}
h1 span {
font-size: 50%;
margin-left: 1em;
font-weight: normal;
}
h2 {
margin: 0;
font-size: 150%;;
}
a:not(#index):target + h2 {
background-color: yellow;
}
h2 ~ p, h2 ~ pre {
margin-left: 1em;
}
p {
margin: 0;
}
p.started {
margin-bottom: 4em;
}
p + p {
margin-top: 1em;
}
pre, tt, h3 {
background-color: #f4f4f4;
border-bottom: 1px solid #ccc;
font-family: "Lucida Console", monospace;
font-size: 90%;
}
pre {
padding: 1em 20px;
overflow: scroll;
}
tt {
margin: 0 1px;
}
h3 {
display: inline-block;
margin: 2em 0 1em 0;
padding: 4px 10px;
border: 0;
background-color: #e0e0e0;
white-space: nowrap;
overflow: scroll;
text-shadow: 0 1px white;
}
a:target + h3 {
background-color: yellow;
}
h2 + h3 {
margin-top: 1em;
}
h3 + br + h3 {
margin-top: 0;
}
h3 span {
opacity: 0.6;
font-weight: normal;
}
main {
margin: 5em 3em 5em 3em;
}
main > div {
-webkit-columns: 32.5em;
-moz-columns: 32.5em;
columns: 32.5em;
-webkit-column-gap: 6em;
-moz-column-gap: 6em;
column-gap: 6em;
}
@media (max-width: 1320px) {
main {
margin-left: 2em;
margin-right: 2em;
}
main > div {
-webkit-column-gap: 4em;
-moz-column-gap: 4em;
column-gap: 4em;
}
header {
padding-left: 2em;
padding-right: 2em;
}
}
@media (max-width: 650px) {
nav {
display: none;
}
main {
margin-left: 0.5em;
margin-right: 0.5em;
}
header {
padding-left: 0.5em;
padding-right: 0.5em;
}
pre {
padding-left: 0;
padding-right: 0;
}
h2 ~ p, h2 ~ pre {
margin-left: 0;
}
h3 span {
display: none;
}
}
main > section:nth-child(2) > h2 {
-webkit-column-span: all;
-moz-column-span: all;
column-span: all;
}
main > div > section:not(:first-child):not(:nth-child(2)), ul {
-webkit-column-break-inside: avoid;
page-break-inside: avoid;
break-inside: avoid;
}
main section {
padding-top: 5em;
max-width: 50em;
}
main > section:nth-child(2) {
-webkit-columns: 14em;
}
h4, ul {
margin: 0;
}
ul {
list-style-type: none;
padding-left: 0;
}
h4 {
padding-top: 2em;
padding-bottom: 0.5em;
}
section > h2 > a:last-child {
float: right;
font-size: 60%;
position: relative;
top: 10px;
right: 20px;
font-weight: normal;
letter-spacing: 0;
}
a[id] {
display: block;
position: relative;
top: -7em;
}
a {
text-decoration: none;
color: blue;
}
a:hover {
text-decoration: underline;
}
p a {
font-weight: bold;
}
tt a {
font-weight: inherit;
}
h2 > a:first-child {
color: inherit;
}
header a {
color: white;
margin-right: 3em;
}
h1 a:hover {
text-decoration: none;
text-shadow: 0 0 2px white;
}
nav {
float: right;
position: relative;
top: 2.3em;
right: 6em;
}
em {
padding: 0 2px;
font-style: normal;
font-weight: bold;
text-decoration: underline;
}
footer {
margin: 0.5em;
opacity: 0.6;
font-size: 70%;
}
span.cpp {
letter-spacing: -1px;
font-size: 90%;
}
span.eleven {
letter-spacing: -2px;
font-size: 85%;
}
</style>
</head>
<body>
<header>
<nav>
<a href="https://github.com/aantron/better-enums">
GitHub
</a>
<a href="https://github.com/aantron/better-enums/tree/master/example">
Tutorial
</a>
</nav>
<h1>
<a href="https://github.com/aantron/better-enums">
Better Enums <span>0.8.0</span>
</a>
</h1>
</header>
<main>
<section>
<p class="started">
The best way to get started with Better Enums is to browse the commented
<a href="https://github.com/aantron/better-enums/tree/master/example">
examples</a>, which form a kind of tutorial. This page gives reference
documentation.
</p>
<p>The following declaration</p>
<pre>#include &lt;enum.h&gt;
ENUM(Enum, underlying_type, A, B, C);</pre>
<p>
generates a new type <tt>Enum</tt>. It is notionally similar to the type
created by this declaration:
</p>
<pre>enum class Enum : underlying_type {A, B, C};</pre>
<p>
that is, it is an enumerated type with constants <tt>Enum::A</tt>,
<tt>Enum::B</tt>, and <tt>Enum::C</tt>, and is represented in memory by an
integer of type <tt>underlying_type</tt>. Just like with a built-in
<tt>enum class</tt>, it is possible to specify numeric values and aliases
for constants:
</p>
<pre>ENUM(Enum, underlying_type, A = 1, B, C, D = A);</pre>
<p>
Constant values are assigned by the compiler by exactly the same rules as
for a built-in enum, so in the above example, <tt>Enum::A == 1</tt>,
<tt>Enum::B == 2</tt>, <tt>Enum::C == 3</tt>, and <tt>Enum::D == 1</tt>.
</p>
</section>
<section>
<a id="index"></a>
<h2>Member index</h2>
<ul>
<h4><a href="#enumerated">Internal enumerated type</a></h4>
<li><a href="#typename-enumerated">typename _Enumerated</a></li>
<li><a href="#constructor">Enum(_Enumerated)</a></li>
<li><a href="#operator+">operator +(_Enumerated)</a></li>
<li><a href="#cast">operator _Enumerated()</a></li>
</ul>
<ul>
<h4><a href="#integral">Integral type</a></h4>
<li><a href="#typename-integral">typename _Integral</a></li>
<li><a href="#from_integral">_from_integral</a></li>
<li><a href="#from_integral_unchecked">_from_integral_unchecked</a></li>
<li><a href="#to_integral">to_integral</a></li>
<li><a href="#is_valid-integral">_is_valid</a></li>
</ul>
<ul>
<h4><a href="#string">String conversions</a></h4>
<li><a href="#from_string">_from_string</a></li>
<li><a href="#from_string_nocase">_from_string_nocase</a></li>
<li><a href="#to_string">to_string</a></li>
<li><a href="#name">_name</a></li>
<li><a href="#is_valid-string">_is_valid</a></li>
<li><a href="#is_valid_nocase">_is_valid_nocase</a></li>
</ul>
<ul>
<h4><a href="#iteration">Iteration</a></h4>
<li><a href="#values">_values</a></li>
<li><a href="#names">_names</a></li>
</ul>
<ul>
<h4><a href="#range">Range properties</a></h4>
<li><a href="#first">_first</a></li>
<li><a href="#last">_last</a></li>
<li><a href="#min">_min</a></li>
<li><a href="#max">_max</a></li>
<li><a href="#size">_size</a></li>
<li><a href="#span">_span</a></li>
</ul>
<ul>
<h4><a href="#comparison">Comparisons</a></h4>
</ul>
<ul>
<h4><a href="#safety">Additional type safety</a></h4>
</ul>
</section>
<div>
<section>
<a id="enumerated"></a>
<h2>
<a href="#enumerated">Internal enumerated type</a>
<a href="#index">index</a>
</h2>
<a id="typename-enumerated"></a>
<h3><span>typename</span> Enum::_Enumerated</h3>
<p>
The declared type <tt>Enum</tt> is built around an internal
<span class="cpp">C++</span> enumeration. Notionally,
</p>
<pre>ENUM(Enum, int, A, B, C);</pre>
<p>produces</p>
<pre>class Enum {
...
public:
enum _Enumerated : int {A, B, C};
...
};</pre>
<p>
<tt>_Enumerated</tt> is simply the name of the internal enumeration. The
user should not use this type name directly, but it is referred to in the
rest of the documentation. The name is exposed because a literal
<tt>Enum::A</tt> is not a value of type <tt>Enum</tt>, but a value of type
<tt>Enum::_Enumerated</tt>, which is convertible to <tt>Enum</tt>, in most
cases implicitly.
</p>
<p>
Note that <tt>_Enumerated</tt> is not a
<span class="cpp">C++</span><span class="eleven">11</span>
<tt>enum class</tt>.
</p>
<a id="constructor"></a>
<h3>
<span>implicit constructor constexpr</span> Enum(_Enumerated)
</h3>
<p>
A converting constructor for promoting values of type <tt>_Enumerated</tt>
to values of type <tt>Enum</tt>. As mentioned above, this typically happens
automatically when you write a literal constant such as <tt>Enum::A</tt> in
a context where a value of type <tt>Enum</tt> is expected. For example:
</p>
<pre>void do_something(Enum value) { ... }
do_something(Enum::A); // converted silently</pre>
<a id="operator+"></a>
<h3>
<span>global unary constexpr</span> operator +(_Enumerated)
</h3>
<p>
For use when the compiler does not choose the implicit constructor above.
For example:
</p>
<pre>(Enum::A).to_string()</pre>
<p>
This expression does not compile because <tt>Enum::A</tt> is not an object,
and the compiler does not promote it. The promotion can be forced:
</p>
<pre>(+Enum::A).to_string()</pre>
<p>
This is easier to maintain than writing out a call to the converting
constructor:
</p>
<pre>((Enum)Enum::A).to_string()</pre>
<a id="cast"></a>
<h3>
<span>casting constexpr</span> operator _Enumerated() <span>const</span>
</h3>
<p>
Enables implicit conversion of <tt>Enum</tt> values down to
<tt>_Enumerated</tt>. The only purpose of this is to make <tt>Enum</tt>
values directly usable in <tt>switch</tt> statements for compiler-supported
case checking:
</p>
<pre>switch(enum_value) {
case Enum::A: ...; break;
case Enum::B: ...; break;
case Enum::C: ...; break;
}</pre>
<p>
It is, unfortunately, a hole in the type safety of <tt>Enum</tt>, since it
allows implicit conversions to integral types (<tt>Enum</tt> to
<tt>_Enumerated</tt>, then <tt>_Enumerated</tt> to an integer). The user
should not rely on such conversions. They will probably be eliminated in the
future, perhaps by replacing this conversion with a conversion to an
<tt>enum class</tt>.
</p>
</section>
<section>
<a id="integral"></a>
<h2>
<a href="#integral">Underlying integral type</a>
<a href="#index">index</a>
</h2>
<a id="typename-integral"></a>
<h3><span>typename</span> Enum::_Integral</h3>
<p>
An alias for the underlying type that <tt>Enum</tt> was declared with. For
example, if the declaration is
</p>
<pre>ENUM(Enum, uint32_t, A, B, C);</pre>
<p>
Then <tt>Enum::_Integral</tt> is the same as <tt>uint32_t</tt>.
</p>
<a id="from_integral"></a>
<h3><span>static constexpr</span> Enum _from_integral(_Integral)</h3>
<p>
Checked cast from a numeric value to an enum value. The function checks that
there is an enum constant with the given value. If not, it <em>throws</em>
<tt>std::runtime_error</tt>. The check takes time <em>linear</em> in the
number of constants in <tt>Enum</tt>.
</p>
<a id="from_integral_unchecked"></a>
<h3>
<span>static constexpr</span> Enum _from_integral_unchecked(_Integral)
</h3>
<p>
Unchecked cast from a numeric value to an enum value. The function assumes
that there is an enum constant with the given value. The user has to ensure
that this assumption holds. If not, the behavior of subsequent operations
on the returned enum value is undefined.
</p>
<a id="to_integral"></a>
<h3>
<span>member constexpr</span>
_Integral enum_value.to_integral() <span>const</span>
</h3>
<p>
Returns the numeric representation of an enum value.
</p>
<a id="is_valid-integral"></a>
<h3><span>static constexpr</span> bool _is_valid(_Integral)</h3>
<p>
Checks that the given numeric value represents one of the constants in
<tt>Enum</tt>, as in <tt>_from_integral</tt>. Complexity is <em>linear</em>
in the number of constants.
</p>
<h3><span>invariant </span> sizeof(Enum) == sizeof(Enum::_Integral)</h3>
<h3><span>invariant </span> alignof(Enum) == alignof(Enum::_Integral)</h3>
</section>
<section>
<a id="string"></a>
<h2>
<a href="#string">String conversions</a>
<a href="#index">index</a>
</h2>
<a id="from_string"></a>
<h3><span>static constexpr</span> Enum _from_string(const char*)</h3>
<p>
Returns the enum constant given by the string. For example:
</p>
<pre>Enum::_from_string("A") == Enum::A</pre>
<p>
Complexity is <em>linear</em> in the number of constants multiplied by the
length of the longest constant name. If the string does not name a constant,
<em>throws</em> <tt>std::runtime_error</tt>.
</p>
<a id="from_string_nocase"></a>
<h3><span>static constexpr</span> Enum _from_string_nocase(const char*)</h3>
<p>
The same as above, but lookup is case-insensitive.
</p>
<a id="to_string"></a>
<h3>
<span>member</span> const char* enum_value.to_string()
<span>const</span>
</h3>
<p>
Returns the string representation of enum value on which the method is
called. If multiple constants have the same numeric value, the string
returned can be the representation any of the constants. Note that this
method is <em>not</em> <tt>constexpr</tt>. Complexity is <em>linear</em> in
the number of constants. If the string does not name a constant,
<em>throws</em> <tt>std::runtime_error</tt>.
</p>
<a id="name"></a>
<h3><span>static constexpr</span> const char *_name</h3>
<p>
The name of the type, i.e., for
</p>
<pre>ENUM(Enum, int, A, B, C);</pre>
<p>
<tt>Enum::_name == "Enum"</tt>
</p>
<a id="is_valid-string"></a>
<h3><span>static constexpr</span> bool _is_valid(const char*)</h3>
<p>
Checks that the given string is the name of one of the constants in
<tt>Enum</tt>, as in <tt>_from_string</tt>, with the same complexity.
</p>
<a id="is_valid_nocase"></a>
<h3><span>static constexpr</span> bool _is_valid_nocase(const char*)</h3>
<p>
The same as above, but corresponding to <tt>_from_string_nocase</tt>.
</p>
</section>
<section>
<a id="iteration"></a>
<h2>
<a href="#iteration">Iteration</a>
<a href="#index">index</a>
</h2>
<a id="values"></a>
<h3><span>static constexpr</span> _ValueIterable values</h3>
<p>
An iterable container with all the defined constant values, in declaration
order. Suitable for use with range-based <tt>for</tt> loops:
</p>
<pre>for (Enum value : Enum::_values) {
// Will iterate over Enum::A, Enum::B, Enum::C
}</pre>
<h3><span>class</span> _ValueIterable::iterator</h3>
<p>
An iterator over defined constant values with a <tt>constexpr</tt>
dereference operator. Can be created explicitly by the <tt>constexpr</tt>
expressions
</p>
<pre>Enum::_values::begin()
Enum::_values::end()</pre>
<a id="names"></a>
<h3><span>static constexpr</span> _NameIterable names</h3>
<p>
An iterable container with the names of the defined constant values, in
declaration order. Suitable for use with range-based <tt>for</tt> loops:
</p>
<pre>for (const char *name : Enum::_names) {
// Will iterate over "A", "B", "C"
}</pre>
<h3><span>class</span> _NameIterable::iterator</h3>
<p>
An iterator over defined constant names with a dereference operator that is
<em>not</em> <tt>constexpr</tt>. Can be created explicitly by the
<tt>constexpr</tt> expressions
</p>
<pre>Enum::_names::begin()
Enum::_names::end()</pre>
</section>
<section>
<a id="range"></a>
<h2>
<a href="#range">Range properties</a>
<a href="#index">index</a>
</h2>
<a id="first"></a>
<h3><span>static constexpr</span> _Enumerated _first</h3>
<p>
The first defined constant. For example, in
</p>
<pre>ENUM(Enum, int, A = 1, B = 5, C = 0);</pre>
<p><tt>Enum::_first == Enum::A</tt></p>
<a id="last"></a>
<h3><span>static constexpr</span> _Enumerated _last</h3>
<p>
The last defined constant, i.e. <tt>Enum::C</tt> in the above example.
</p>
<a id="min"></a>
<h3><span>static constexpr</span> _Enumerated _min</h3>
<p>
The defined constant with the smallest numeric value, i.e. <tt>Enum::C</tt>
in the above example.
</p>
<a id="max"></a>
<h3><span>static constexpr</span> _Enumerated _max</h3>
<p>
The defined constant with the greatest numeric value, i.e. <tt>Enum::B</tt>
in the above example.
</p>
<a id="size"></a>
<h3><span>static constexpr</span> size_t _size</h3>
<p>
The number of constants defined, i.e. 3 in the above example.
</p>
<a id="span"></a>
<h3><span>static constexpr</span> _Integral _span</h3>
<p>
The numeric span of the constants defined, i.e. <tt>_max - _min + 1</tt>,
which is 6 in the above example.
</p>
</section>
<section>
<a id="comparison"></a>
<h2>
<a href="#comparison">Comparisons</a>
<a href="#index">index</a>
</h2>
<h3>
<span>member constexpr</span> bool operator ==(const Enum&amp;)
<span>const</span>
</h3>
<h3>
<span>member constexpr</span> bool operator ==(_Enumerated)
<span>const</span>
</h3>
<h3>
<span>member constexpr</span> bool operator !=(const Enum&amp;)
<span>const</span>
</h3>
<h3>
<span>member constexpr</span> bool operator !=(_Enumerated)
<span>const</span>
</h3>
<h3>
<span>member constexpr</span> bool operator &lt;(const Enum&amp;)
<span>const</span>
</h3>
<h3>
<span>member constexpr</span> bool operator &lt;(_Enumerated)
<span>const</span>
</h3>
<h3>
<span>member constexpr</span> bool operator &lt;=(const Enum&amp;)
<span>const</span>
</h3>
<h3>
<span>member constexpr</span> bool operator &lt;=(_Enumerated)
<span>const</span>
</h3>
<h3>
<span>member constexpr</span> bool operator &gt;(const Enum&amp;)
<span>const</span>
</h3>
<h3>
<span>member constexpr</span> bool operator &gt;(_Enumerated)
<span>const</span>
</h3>
<h3>
<span>member constexpr</span> bool operator &gt;=(const Enum&amp;)
<span>const</span>
</h3>
<h3>
<span>member constexpr</span> bool operator &gt;=(_Enumerated)
<span>const</span>
</h3>
<p>
These define an ordering on values of types <tt>Enum</tt> and
<tt>Enum::_Enumerated</tt>. The ordering is according to the values'
numeric representations. That means that two values that have been aliased
will compare equal. Direct comparisons with all other types are forbidden;
this is enforced by deleted comparison operators for all other types.
</p>
</section>
<section>
<a id="safety"></a>
<h2>
<a href="#safety">Additional type safety</a>
<a href="#index">index</a>
</h2>
<h3><span>default constructor</span> Enum() = delete</h3>
<p>
The default constructor is deleted to encourage initialization with valid
values only and to avoid undefined states. See
<a href="https://github.com/aantron/better-enums/blob/master/example/6-traits.cc">
example/6-traits.cc</a> for an example of how to add an explicit notion of
default value.
</p>
<h3><span>invariant</span> no arithmetic</h3>
<p>Arithmetic operators are explicitly deleted.</p>
<h3><span>invariant</span> no implicit conversion from integers</h3>
</section>
</div>
</main>
<footer>
Copyright &copy; 2015.
Distributed under the BSD 2-clause license. See
<a href="https://github.com/aantron/better-enums/blob/master/LICENSE">
LICENSE</a>.
</footer>
<script>
var property_headers = document.querySelectorAll("h3");
for (var index = 0; index < property_headers.length; ++index) {
var br = document.createElement("br");
var header = property_headers[index];
var next = header.nextSibling;
console.log(header);
console.log(header.parentNode);
if (next === null)
header.parentNode.appendChild(br);
else
header.parentNode.insertBefore(br, next);
}
</script>
</body>
</html>

534
enum.h Normal file
View File

@ -0,0 +1,534 @@
// This file is part of Better Enums, released under the BSD 2-clause license.
// See LICENSE for details, or visit http://github.com/aantron/better-enums.
#pragma once
#ifndef _BETTER_ENUM_ENUM_H_
#define _BETTER_ENUM_ENUM_H_
#include <cstddef> // For size_t.
#include <cstring> // For string and memory routines.
#include <stdexcept>
#include <type_traits>
#include "enum_preprocessor_map.h"
namespace _enum {
#define _ENUM_WEAK __attribute__((weak))
template <typename EnumType, typename Iterator>
class _Iterable;
template <typename Derived>
class _BaseIterator {
public:
Derived& operator ++()
{ ++_index; return static_cast<Derived&>(*this); }
constexpr bool operator ==(const Derived &other) const
{ return other._index == _index; }
constexpr bool operator !=(const Derived &other) const
{ return other._index != _index; }
protected:
constexpr _BaseIterator(size_t index) : _index(index) { }
size_t _index;
};
template <typename EnumType>
class _ValueIterator :
public _BaseIterator<_ValueIterator<EnumType>> {
using _Super = _BaseIterator<_ValueIterator<EnumType>>;
public:
constexpr EnumType operator *() const
{ return EnumType::_value_array[_Super::_index]; }
private:
using _Super::_Super;
friend _Iterable<EnumType, _ValueIterator<EnumType>>;
};
template <typename EnumType>
class _NameIterator :
public _BaseIterator<_NameIterator<EnumType>> {
using _Super = _BaseIterator<_NameIterator<EnumType>>;
public:
const char* operator *() const
{ return EnumType::_getProcessedName(_Super::_index); }
private:
using _Super::_Super;
friend _Iterable<EnumType, _NameIterator<EnumType>>;
};
template <typename EnumType, typename Iterator>
class _Iterable {
public:
using iterator = Iterator;
constexpr iterator begin() const { return iterator(0); }
constexpr iterator end() const { return iterator(EnumType::_size); }
constexpr size_t size() const { return EnumType::_size; }
private:
constexpr _Iterable() { };
friend EnumType;
};
template <typename UnderlyingType>
class _eat_assign {
private:
UnderlyingType _value;
public:
explicit constexpr _eat_assign(UnderlyingType value) : _value(value) { }
template <typename Any>
constexpr UnderlyingType operator =(Any dummy) const
{ return _value; }
constexpr operator UnderlyingType () const { return _value; }
};
#define _ENUM_EAT_ASSIGN_SINGLE(UnderlyingType, expression) \
((_enum::_eat_assign<UnderlyingType>)expression)
#define _ENUM_EAT_ASSIGN(UnderlyingType, ...) \
_ENUM_PP_MAP(_ENUM_EAT_ASSIGN_SINGLE, UnderlyingType, __VA_ARGS__)
#define _ENUM_STRINGIZE_SINGLE(ignored, expression) #expression
#define _ENUM_STRINGIZE(...) \
_ENUM_PP_MAP(_ENUM_STRINGIZE_SINGLE, ignored, __VA_ARGS__)
#define _ENUM_NAME_ENDERS "= \t\n"
constexpr bool _endsName(char c, size_t index = 0)
{
return
// First, test whether c is equal to the current character in
// _ENUM_NAME_ENDERS. In the case where c is the null terminator, this
// will cause _endsName to return true when it has exhausted
// _ENUM_NAME_ENDERS.
c == _ENUM_NAME_ENDERS[index] ? true :
// If _ENUM_NAME_ENDERS has been exhausted and c never matched, return
// false.
_ENUM_NAME_ENDERS[index] == '\0' ? false :
// Otherwise, go on to the next character in _ENUM_ENDERS.
_endsName(c, index + 1);
}
constexpr char _toLowercaseAscii(char c)
{
return c >= 0x41 && c <= 0x5A ? c + 0x20 : c;
}
constexpr bool _namesMatch(const char *stringizedName,
const char *referenceName,
size_t index = 0)
{
return
// If the current character in the stringized name is a name ender,
// return true if the reference name ends as well, and false otherwise.
_endsName(stringizedName[index]) ? referenceName[index] == '\0' :
// The current character in the stringized name is not a name ender. If
// the reference name ended, then it is too short, so return false.
referenceName[index] == '\0' ? false :
// Neither name has ended. If the two current characters don't match,
// return false.
stringizedName[index] !=
referenceName[index] ? false :
// Otherwise, if the characters match, continue by comparing the rest of
// the names.
_namesMatch(stringizedName, referenceName, index + 1);
}
constexpr bool _namesMatchNocase(const char *stringizedName,
const char *referenceName,
size_t index = 0)
{
return
_endsName(stringizedName[index]) ? referenceName[index] == '\0' :
referenceName[index] == '\0' ? false :
_toLowercaseAscii(stringizedName[index]) !=
_toLowercaseAscii(referenceName[index]) ? false :
_namesMatchNocase(stringizedName, referenceName, index + 1);
}
template <typename UnderlyingType>
constexpr UnderlyingType _findMinLoop(const UnderlyingType *values,
size_t valueCount, size_t index,
UnderlyingType best)
{
return
index == valueCount ? best :
values[index] < best ?
_findMinLoop(values, valueCount, index + 1, values[index]) :
_findMinLoop(values, valueCount, index + 1, best);
}
template <typename UnderlyingType>
constexpr UnderlyingType _findMin(const UnderlyingType *values,
size_t valueCount)
{
return _findMinLoop(values, valueCount, 1, values[0]);
}
template <typename UnderlyingType>
constexpr UnderlyingType _findMaxLoop(const UnderlyingType *values,
size_t valueCount, size_t index,
UnderlyingType best)
{
return
index == valueCount ? best :
values[index] > best ?
_findMaxLoop(values, valueCount, index + 1, values[index]) :
_findMaxLoop(values, valueCount, index + 1, best);
}
template <typename UnderlyingType>
constexpr UnderlyingType _findMax(const UnderlyingType *values, size_t count)
{
return _findMaxLoop(values, count, 1, values[0]);
}
static inline const char * const* _processNames(const char * const *rawNames,
size_t count)
{
// Allocate the replacement names array.
const char **processedNames = new const char*[count];
if (processedNames == nullptr)
return nullptr;
// Count the number of bytes needed in the replacement names array (an upper
// bound).
size_t bytesNeeded = 0;
for (size_t index = 0; index < count; ++index)
bytesNeeded += std::strlen(rawNames[index]) + 1;
// Allocate memory for the string data.
char *nameStorage = new char[bytesNeeded];
if (nameStorage == nullptr) {
delete[] processedNames;
return nullptr;
}
// Trim each name and place the result in storage, then save a pointer to
// it.
char *writePointer = nameStorage;
for (size_t index = 0; index < count; ++index) {
const char *nameEnd =
std::strpbrk(rawNames[index], _ENUM_NAME_ENDERS);
size_t symbolCount =
nameEnd == nullptr ?
std::strlen(rawNames[index]) :
nameEnd - rawNames[index];
std::strncpy(writePointer, rawNames[index], symbolCount);
processedNames[index] = writePointer;
writePointer += symbolCount;
*writePointer = '\0';
++writePointer;
}
return processedNames;
}
#define _ENUM_TAG(EnumType) _tag_ ## EnumType
#define _ENUM_TAG_DECLARATION(EnumType) \
namespace _enum { \
struct _ENUM_TAG(EnumType); \
}
template <typename Tag> class _GeneratedArrays;
#define _ENUM_ARRAYS(EnumType, Integral, Tag, ...) \
namespace _enum { \
\
template <> \
class _GeneratedArrays<Tag> { \
protected: \
using _Integral = Integral; \
\
public: \
constexpr static const char* _name = #EnumType; \
\
enum _Enumerated : _Integral { __VA_ARGS__ }; \
\
protected: \
constexpr static _Enumerated _value_array[] = \
{ _ENUM_EAT_ASSIGN(_Enumerated, __VA_ARGS__) }; \
\
constexpr static const char *_name_array[] = \
{ _ENUM_STRINGIZE(__VA_ARGS__) }; \
}; \
\
}
#define _ENUM_NOT_FOUND ((size_t)-1)
template <typename Tag>
class _Enum : public _GeneratedArrays<Tag> {
protected:
using _arrays = _GeneratedArrays<Tag>;
using _arrays::_value_array;
using _arrays::_name_array;
public:
using typename _arrays::_Enumerated;
using typename _arrays::_Integral;
constexpr static const size_t _size =
sizeof(_value_array) / sizeof(_Enumerated);
static_assert(_size > 0, "no constants defined in enum type");
constexpr static const _Enumerated _first = _value_array[0];
constexpr static const _Enumerated _last = _value_array[_size - 1];
constexpr static const _Enumerated _min = _findMin(_value_array, _size);
constexpr static const _Enumerated _max = _findMax(_value_array, _size);
constexpr static const _Integral _span = _max - _min + 1;
_Enum() = delete;
constexpr _Enum(_Enumerated constant) : _value(constant) { }
constexpr _Integral to_integral() const
{
return _value;
}
constexpr static const _Enum _from_integral(_Integral value)
{
return _value_array[_from_int_loop(value, true)];
}
constexpr static const _Enum _from_integral_unchecked(_Integral value)
{
return (_Enumerated)value;
}
const char* to_string() const
{
_processNames();
for (size_t index = 0; index < _size; ++index) {
if (_value_array[index] == _value)
return _processedNames[index];
}
throw std::domain_error("Enum::_to_string: invalid enum value");
}
constexpr static const _Enum _from_string(const char *name)
{
return _value_array[_from_string_loop(name, true)];
}
constexpr static const _Enum _from_string_nocase(const char *name)
{
return _value_array[_from_string_nocase_loop(name, true)];
}
constexpr static bool _is_valid(_Integral value)
{
return _from_int_loop(value, false) != _ENUM_NOT_FOUND;
}
constexpr static bool _is_valid(const char *name)
{
return _from_string_loop(name, false) != _ENUM_NOT_FOUND;
}
constexpr static bool _is_valid_nocase(const char *name)
{
return _from_string_nocase_loop(name, false) != _ENUM_NOT_FOUND;
}
constexpr operator _Enumerated() const { return _value; }
protected:
_Enumerated _value;
static const char * const *_processedNames;
static void _processNames()
{
if (_processedNames == nullptr)
_processedNames = _enum::_processNames(_name_array, _size);
}
static const char* _getProcessedName(size_t index)
{
_processNames();
return _processedNames[index];
}
using _ValueIterable = _Iterable<_Enum, _ValueIterator<_Enum>>;
using _NameIterable = _Iterable<_Enum, _NameIterator<_Enum>>;
friend _ValueIterator<_Enum>;
friend _NameIterator<_Enum>;
public:
static const _ValueIterable _values;
static const _NameIterable _names;
protected:
constexpr static size_t _from_int_loop(_Integral value,
bool throw_exception,
size_t index = 0)
{
return
index == _size ?
(throw_exception ?
throw std::runtime_error(
"Enum::_from_integral: invalid integer value") :
_ENUM_NOT_FOUND) :
_value_array[index] == value ? index :
_from_int_loop(value, throw_exception, index + 1);
}
constexpr static size_t _from_string_loop(const char *name,
bool throw_exception,
size_t index = 0)
{
return
index == _size ?
(throw_exception ?
throw std::runtime_error(
"Enum::_from_string: invalid string argument") :
_ENUM_NOT_FOUND) :
_namesMatch(_name_array[index], name) ? index :
_from_string_loop(name, throw_exception, index + 1);
}
constexpr static size_t _from_string_nocase_loop(const char *name,
bool throw_exception,
size_t index = 0)
{
return
index == _size ?
(throw_exception ?
throw std::runtime_error(
"Enum::_from_string_nocase: invalid string argument") :
_ENUM_NOT_FOUND) :
_namesMatchNocase(_name_array[index], name) ? index :
_from_string_nocase_loop(name, throw_exception, index + 1);
}
public:
constexpr bool operator ==(const _Enum &other) const
{ return _value == other._value; }
constexpr bool operator ==(const _Enumerated value) const
{ return _value == value; }
template <typename T> bool operator ==(T other) const = delete;
constexpr bool operator !=(const _Enum &other) const
{ return !(*this == other); }
constexpr bool operator !=(const _Enumerated value) const
{ return !(*this == value); }
template <typename T> bool operator !=(T other) const = delete;
constexpr bool operator <(const _Enum &other) const
{ return _value < other._value; }
constexpr bool operator <(const _Enumerated value) const
{ return _value < value; }
template <typename T> bool operator <(T other) const = delete;
constexpr bool operator <=(const _Enum &other) const
{ return _value <= other._value; }
constexpr bool operator <=(const _Enumerated value) const
{ return _value <= value; }
template <typename T> bool operator <=(T other) const = delete;
constexpr bool operator >(const _Enum &other) const
{ return _value > other._value; }
constexpr bool operator >(const _Enumerated value) const
{ return _value > value; }
template <typename T> bool operator >(T other) const = delete;
constexpr bool operator >=(const _Enum &other) const
{ return _value >= other._value; }
constexpr bool operator >=(const _Enumerated value) const
{ return _value >= value; }
template <typename T> bool operator >=(T other) const = delete;
int operator -() const = delete;
template <typename T> int operator +(T other) const = delete;
template <typename T> int operator -(T other) const = delete;
template <typename T> int operator *(T other) const = delete;
template <typename T> int operator /(T other) const = delete;
template <typename T> int operator %(T other) const = delete;
template <typename T> int operator <<(T other) const = delete;
template <typename T> int operator >>(T other) const = delete;
int operator ~() const = delete;
template <typename T> int operator &(T other) const = delete;
template <typename T> int operator |(T other) const = delete;
template <typename T> int operator ^(T other) const = delete;
int operator !() const = delete;
template <typename T> int operator &&(T other) const = delete;
template <typename T> int operator ||(T other) const = delete;
};
#define _ENUM_GLOBALS(EnumType, Tag) \
namespace _enum { \
\
constexpr const EnumType operator +(EnumType::_Enumerated enumerated) \
{ return (EnumType)enumerated; } \
\
template <> \
constexpr EnumType::_ValueIterable _ENUM_WEAK EnumType::_values{}; \
\
template <> \
constexpr EnumType::_NameIterable _ENUM_WEAK EnumType::_names{}; \
\
constexpr _GeneratedArrays<Tag>::_Enumerated _ENUM_WEAK \
_GeneratedArrays<Tag>::_value_array[]; \
\
constexpr const char * _ENUM_WEAK _GeneratedArrays<Tag>::_name_array[]; \
\
template <> \
const char * const * _ENUM_WEAK EnumType::_processedNames = nullptr; \
\
}
} // namespace _enum
#define ENUM(EnumType, Integral, ...) \
_ENUM_TAG_DECLARATION(EnumType); \
_ENUM_ARRAYS(EnumType, Integral, _ENUM_TAG(EnumType), __VA_ARGS__); \
using EnumType = _enum::_Enum<_enum::_ENUM_TAG(EnumType)>; \
_ENUM_GLOBALS(EnumType, _ENUM_TAG(EnumType));
#endif // #ifndef _BETTER_ENUM_ENUM_H_

571
enum_preprocessor_map.h Normal file
View File

@ -0,0 +1,571 @@
/// @file enum_preprocessor_map.h
/// @brief Preprocessor higher-order map macro.
///
/// This file was automatically generated by pp_map_gen.py
#pragma once
#ifndef _BETTER_ENUM_ENUM_PREPROCESSOR_MAP_H_
#define _BETTER_ENUM_ENUM_PREPROCESSOR_MAP_H_
#define _ENUM_PP_MAP(macro, data, ...) \
_ENUM_PP_APPLY(_ENUM_PP_MAP_VAR_COUNT, _ENUM_PP_COUNT(__VA_ARGS__)) \
(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_VAR_COUNT(count) _ENUM_PP_MAP_ ## count
#define _ENUM_PP_APPLY(macro, ...) macro(__VA_ARGS__)
#define _ENUM_PP_MAP_1(macro, data, x) _ENUM_PP_APPLY(macro, data, x)
#define _ENUM_PP_MAP_2(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_1(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_3(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_2(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_4(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_3(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_5(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_4(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_6(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_5(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_7(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_6(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_8(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_7(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_9(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_8(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_10(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_9(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_11(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_10(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_12(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_11(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_13(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_12(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_14(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_13(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_15(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_14(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_16(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_15(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_17(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_16(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_18(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_17(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_19(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_18(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_20(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_19(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_21(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_20(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_22(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_21(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_23(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_22(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_24(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_23(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_25(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_24(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_26(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_25(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_27(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_26(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_28(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_27(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_29(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_28(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_30(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_29(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_31(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_30(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_32(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_31(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_33(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_32(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_34(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_33(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_35(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_34(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_36(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_35(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_37(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_36(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_38(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_37(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_39(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_38(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_40(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_39(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_41(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_40(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_42(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_41(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_43(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_42(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_44(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_43(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_45(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_44(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_46(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_45(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_47(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_46(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_48(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_47(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_49(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_48(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_50(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_49(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_51(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_50(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_52(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_51(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_53(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_52(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_54(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_53(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_55(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_54(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_56(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_55(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_57(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_56(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_58(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_57(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_59(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_58(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_60(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_59(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_61(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_60(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_62(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_61(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_63(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_62(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_64(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_63(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_65(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_64(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_66(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_65(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_67(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_66(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_68(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_67(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_69(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_68(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_70(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_69(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_71(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_70(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_72(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_71(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_73(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_72(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_74(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_73(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_75(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_74(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_76(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_75(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_77(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_76(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_78(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_77(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_79(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_78(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_80(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_79(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_81(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_80(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_82(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_81(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_83(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_82(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_84(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_83(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_85(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_84(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_86(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_85(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_87(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_86(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_88(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_87(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_89(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_88(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_90(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_89(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_91(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_90(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_92(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_91(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_93(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_92(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_94(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_93(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_95(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_94(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_96(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_95(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_97(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_96(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_98(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_97(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_99(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_98(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_100(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_99(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_101(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_100(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_102(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_101(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_103(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_102(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_104(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_103(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_105(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_104(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_106(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_105(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_107(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_106(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_108(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_107(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_109(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_108(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_110(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_109(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_111(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_110(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_112(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_111(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_113(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_112(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_114(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_113(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_115(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_114(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_116(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_115(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_117(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_116(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_118(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_117(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_119(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_118(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_120(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_119(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_121(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_120(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_122(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_121(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_123(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_122(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_124(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_123(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_125(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_124(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_126(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_125(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_127(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_126(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_128(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_127(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_129(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_128(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_130(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_129(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_131(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_130(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_132(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_131(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_133(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_132(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_134(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_133(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_135(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_134(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_136(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_135(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_137(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_136(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_138(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_137(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_139(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_138(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_140(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_139(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_141(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_140(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_142(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_141(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_143(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_142(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_144(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_143(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_145(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_144(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_146(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_145(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_147(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_146(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_148(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_147(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_149(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_148(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_150(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_149(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_151(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_150(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_152(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_151(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_153(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_152(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_154(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_153(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_155(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_154(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_156(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_155(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_157(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_156(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_158(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_157(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_159(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_158(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_160(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_159(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_161(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_160(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_162(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_161(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_163(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_162(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_164(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_163(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_165(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_164(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_166(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_165(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_167(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_166(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_168(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_167(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_169(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_168(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_170(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_169(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_171(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_170(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_172(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_171(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_173(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_172(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_174(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_173(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_175(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_174(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_176(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_175(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_177(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_176(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_178(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_177(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_179(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_178(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_180(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_179(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_181(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_180(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_182(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_181(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_183(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_182(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_184(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_183(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_185(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_184(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_186(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_185(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_187(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_186(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_188(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_187(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_189(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_188(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_190(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_189(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_191(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_190(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_192(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_191(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_193(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_192(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_194(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_193(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_195(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_194(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_196(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_195(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_197(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_196(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_198(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_197(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_199(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_198(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_200(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_199(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_201(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_200(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_202(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_201(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_203(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_202(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_204(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_203(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_205(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_204(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_206(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_205(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_207(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_206(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_208(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_207(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_209(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_208(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_210(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_209(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_211(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_210(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_212(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_211(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_213(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_212(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_214(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_213(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_215(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_214(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_216(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_215(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_217(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_216(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_218(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_217(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_219(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_218(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_220(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_219(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_221(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_220(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_222(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_221(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_223(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_222(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_224(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_223(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_225(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_224(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_226(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_225(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_227(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_226(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_228(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_227(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_229(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_228(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_230(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_229(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_231(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_230(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_232(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_231(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_233(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_232(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_234(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_233(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_235(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_234(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_236(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_235(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_237(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_236(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_238(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_237(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_239(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_238(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_240(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_239(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_241(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_240(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_242(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_241(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_243(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_242(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_244(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_243(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_245(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_244(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_246(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_245(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_247(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_246(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_248(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_247(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_249(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_248(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_250(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_249(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_251(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_250(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_252(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_251(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_253(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_252(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_254(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_253(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_255(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_254(macro, data, __VA_ARGS__)
#define _ENUM_PP_MAP_256(macro, data, x, ...) _ENUM_PP_APPLY(macro, data, x), \
_ENUM_PP_MAP_255(macro, data, __VA_ARGS__)
#define _ENUM_PP_COUNT_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, \
_13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, \
_28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, \
_43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, \
_58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, \
_73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, \
_88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, _101, \
_102, _103, _104, _105, _106, _107, _108, _109, _110, _111, _112, _113, \
_114, _115, _116, _117, _118, _119, _120, _121, _122, _123, _124, _125, \
_126, _127, _128, _129, _130, _131, _132, _133, _134, _135, _136, _137, \
_138, _139, _140, _141, _142, _143, _144, _145, _146, _147, _148, _149, \
_150, _151, _152, _153, _154, _155, _156, _157, _158, _159, _160, _161, \
_162, _163, _164, _165, _166, _167, _168, _169, _170, _171, _172, _173, \
_174, _175, _176, _177, _178, _179, _180, _181, _182, _183, _184, _185, \
_186, _187, _188, _189, _190, _191, _192, _193, _194, _195, _196, _197, \
_198, _199, _200, _201, _202, _203, _204, _205, _206, _207, _208, _209, \
_210, _211, _212, _213, _214, _215, _216, _217, _218, _219, _220, _221, \
_222, _223, _224, _225, _226, _227, _228, _229, _230, _231, _232, _233, \
_234, _235, _236, _237, _238, _239, _240, _241, _242, _243, _244, _245, \
_246, _247, _248, _249, _250, _251, _252, _253, _254, _255, _256, count, \
...) count
#define _ENUM_PP_COUNT(...) _ENUM_PP_COUNT_IMPL(__VA_ARGS__, 256, 255, 254, \
253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, \
238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, \
223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, \
208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, \
193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, \
178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, \
163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, 150, 149, \
148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, \
133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 120, 119, \
118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, 105, 104, \
103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86,\
85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67,\
66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48,\
47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29,\
28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,\
9, 8, 7, 6, 5, 4, 3, 2, 1)
#endif // #ifndef _BETTER_ENUM_ENUM_PREPROCESSOR_MAP_H_

98
example/1-basic.cc Normal file
View File

@ -0,0 +1,98 @@
// Basic conversions to/from strings and the underlying integral type.
#include <iostream>
#include <enum.h>
ENUM(Channel, uint16_t, Red, Green = 2, Blue, Alias = Red);
// Enums should be treated like integers (in memory, Channel is a uint16_t), and
// should generally be passed by value.
void print_channel(Channel channel)
{
std::cout
<< "channel \'"
<< channel.to_string()
<< "\' has value "
<< channel.to_integral()
<< std::endl;
}
int main()
{
// A value must be assigned upon construction.
Channel channel = Channel::Green;
print_channel(channel);
// This will not work, though see example/6-traits.cc for an alternative.
// Channel default_constructed_channel;
// Conversions from strings and the integral type. Static members of Channel
// are prefixed with _ to avoid conflicts with constant names.
// _from_integral is a checked cast.
channel = Channel::_from_integral(0);
print_channel(channel);
channel = Channel::_from_string("Blue");
print_channel(channel);
channel = Channel::_from_string_nocase("bluE");
print_channel(channel);
// Failed conversions.
try {
channel = Channel::_from_integral(15);
throw std::logic_error("expected an exception");
}
catch (const std::runtime_error &e) { }
try {
channel = Channel::_from_string("Purple");
throw std::logic_error("expected an exception");
}
catch (const std::runtime_error &e) { }
try {
channel = Channel::_from_string_nocase("bluee");
throw std::logic_error("expected an exception");
}
catch (const std::runtime_error &e) { }
// Unsafe unchecked cast.
channel = Channel::_from_integral_unchecked(2);
// Direct operations on a constant require a promotion with the unary +
// operator. This is an implementation artifact - constants are not actually
// values of type Channel, but of type Channel::_Enumerated, and the
// compiler isn't always able to implicitly promote the latter to the
// former. + is used to force the promotion.
std::cout << (+Channel::Green).to_string() << std::endl;
// This will not work.
// std::cout << (Channel::Green).to_string() << std::endl;
// The type name is available as a string.
std::cout << Channel::_name << std::endl;
return 0;
}
static_assert(sizeof(Channel) == sizeof(uint16_t),
"enum has the same size as its underlying integral type");
static_assert(alignof(Channel) == alignof(uint16_t),
"enum has the same alignment as its underlying integral type");
static_assert(std::is_same<Channel::_Integral, uint16_t>(),
"the underlying integral type is accessible as a member");

40
example/2-iterate.cc Normal file
View File

@ -0,0 +1,40 @@
// Range properties and iteration over all constants.
#include <iostream>
#include <enum.h>
ENUM(Channel, int, Red = 3, Green = 4, Blue = 0);
int main()
{
// Static range properties. Output is Red, Blue, Blue, Green, 3, 5.
// See 6-traits.cc for an application of _first.
std::cout << "first: " << (+Channel::_first).to_string() << std::endl;
std::cout << "last: " << (+Channel::_last).to_string() << std::endl;
std::cout << "minimum: " << (+Channel::_min).to_string() << std::endl;
std::cout << "maximum: " << (+Channel::_max).to_string() << std::endl;
std::cout << "count: " << Channel::_size << std::endl;
std::cout << "span: " << Channel::_span << std::endl;
// Listing declared values. Output is 3 4 0.
for (Channel channel : Channel::_values)
std::cout << channel.to_integral() << " ";
std::cout << std::endl;
// Listing declared names. Output is Red Green Blue.
for (const char *name : Channel::_names)
std::cout << name << " ";
std::cout << std::endl;
// Direct iterator usage. Output is Red.
std::cout
<< "first (using iterator): "
<< *Channel::_names.begin()
<< std::endl;
return 0;
}

38
example/3-switch.cc Normal file
View File

@ -0,0 +1,38 @@
// Switch case exhaustiveness checking.
#include <iostream>
#include <enum.h>
ENUM(Channel, int, Red, Green, Blue);
void respond_to_channel(Channel channel)
{
// Try adding an extra case or removing one. Your compiler should issue a
// warning.
switch (channel) {
case Channel::Red:
std::cout << "red channel" << std::endl;
break;
case Channel::Green:
std::cout << "green channel" << std::endl;
break;
case Channel::Blue:
std::cout << "blue channel" << std::endl;
break;
// A redundant case.
// case 3:
// break;
}
}
int main()
{
respond_to_channel(Channel::Red);
respond_to_channel(Channel::Blue);
respond_to_channel(Channel::Green);
return 0;
}

92
example/4-constexpr.cc Normal file
View File

@ -0,0 +1,92 @@
// Usage in constexpr expressions. All members of an ENUM are constexpr when
// given constant arguments, with the exception of _to_string and dereferencing
// the _names iterator.
#include <iostream>
#include <enum.h>
ENUM(Channel, int, Red, Green, Blue);
// Initialization.
constexpr Channel channel_1 = Channel::Green;
constexpr Channel channel_4 = Channel::_from_integral(2);
constexpr Channel channel_2 = Channel::_from_string("Blue");
constexpr Channel channel_3 = Channel::_from_string_nocase("gReEn");
// Conversion to integer (but not to string).
constexpr int channel_1_representation = channel_1.to_integral();
// Validity checks (including against strings).
constexpr bool should_be_valid_1 = Channel::_is_valid(2);
constexpr bool should_be_invalid_1 = Channel::_is_valid(42);
constexpr bool should_be_valid_2 = Channel::_is_valid("Red");
constexpr bool should_be_invalid_2 = Channel::_is_valid("red");
constexpr bool should_be_valid_3 = Channel::_is_valid_nocase("red");
constexpr bool should_be_invalid_3 = Channel::_is_valid_nocase("reed");
// _names and _values collections and iterator creation.
constexpr Channel channel_5 = *Channel::_values.begin();
constexpr auto name_iterator = Channel::_names.begin();
// Range properties.
constexpr Channel channel_6 = Channel::_max;
constexpr size_t span = Channel::_span;
// Type name.
constexpr auto name = Channel::_name;
// Explicit promotion.
constexpr int converted = (+Channel::Green).to_integral();
// The above, printed for verification.
void print_channel(int number, Channel channel)
{
std::cout
<< "channel_"
<< number
<< " is "
<< channel.to_string()
<< std::endl;
}
#define PRINT(n) print_channel(n, channel_ ## n)
void print_validity(bool expected, bool actual)
{
std::cout
<< "should be "
<< expected
<< ": "
<< actual
<< std::endl;
}
int main()
{
PRINT(1);
PRINT(2);
PRINT(3);
PRINT(4);
print_validity(true, should_be_valid_1);
print_validity(false, should_be_invalid_1);
print_validity(true, should_be_valid_2);
print_validity(false, should_be_invalid_2);
print_validity(true, should_be_valid_3);
print_validity(false, should_be_invalid_3);
PRINT(5);
PRINT(6);
std::cout << *name_iterator << std::endl;
std::cout << "span: " << span << std::endl;
std::cout << "type name: " << name << std::endl;
return 0;
}

64
example/5-containers.cc Normal file
View File

@ -0,0 +1,64 @@
// Usage with STL containers.
#include <iostream>
#include <map>
#include <vector>
#include <enum.h>
ENUM(Channel, int, Red, Green, Blue);
int main()
{
// Vectors of enums.
std::vector<Channel> vector = {Channel::Red, Channel::Green};
vector.push_back(Channel::Red);
vector.push_back(Channel::Blue);
vector.push_back(Channel::Blue);
vector.push_back(Channel::Red);
for (Channel channel : vector)
std::cout << channel.to_string() << " ";
std::cout << std::endl;
// Maps. Lack of a default constructor in the current version means that
// std::map::operator[] usage is complicated. Insertion can still be done
// with ::insert, and access with ::find.
std::map<const char*, Channel> map = {{"first", Channel::Blue}};
map.insert({"second", Channel::Green});
for (Channel channel : Channel::_values)
map.insert({channel.to_string(), channel});
bool first = true;
for (auto item : map) {
if (first)
first = false;
else
std::cout << ", ";
std::cout
<< item.first
<< " -> "
<< item.second.to_string();
}
std::cout << std::endl;
// Enums as map keys.
std::map<Channel, const char*> descriptions =
{{Channel::Red, "the red channel"},
{Channel::Green, "the green channel"},
{Channel::Blue, "the blue channel"}};
for (auto item : descriptions)
std::cout << item.second << std::endl;
return 0;
}

55
example/6-traits.cc Normal file
View File

@ -0,0 +1,55 @@
// Using traits to capture project conventions on enums.
// In this example, a project wants to have a notion of "default value" for all
// enums. Better Enums doesn't provide this, but it can be added easily with a
// traits class, as shown here.
#include <iostream>
#include <enum.h>
// Adopt the convention that the first value in an enum is the default value.
template <typename Enum>
constexpr const Enum default_()
{
return Enum::_first;
}
// Make it possible to override the convention for specific enums.
#define ENUM_DEFAULT(Enum, Default) \
template <> \
constexpr const Enum default_<Enum>() \
{ \
return Enum::Default; \
}
// Default will be Red, because it is first.
ENUM(Channel, int, Red, Green, Blue);
// Default will be TrueColor, even though it is not first.
ENUM(Depth, int, HighColor, TrueColor);
ENUM_DEFAULT(Depth, TrueColor);
int main()
{
// Default construction can now be simulated for some purposes, and the
// default value is still declared in one place, not all over the program
// code.
Depth depth = default_<Depth>();
std::cout << depth.to_string() << std::endl;
std::cout << default_<Channel>().to_string() << std::endl;
std::cout << default_<Depth>().to_string() << std::endl;
return 0;
}
// Also works at compile-time.
constexpr auto value = default_<Channel>();

33
example/7-bitset.cc Normal file
View File

@ -0,0 +1,33 @@
// Usage with std::bitset.
#include <bitset>
#include <iostream>
#include <enum.h>
ENUM(Channel, int, Red, Green, Blue);
int main()
{
using ChannelSet = std::bitset<Channel::_span>;
ChannelSet red_only;
red_only.set(Channel::Red);
ChannelSet blue_only;
blue_only.set(Channel::Blue);
ChannelSet red_and_blue = red_only | blue_only;
for (Channel channel : Channel::_values) {
std::cout
<< channel.to_string()
<< " bit is set to "
<< red_and_blue[channel]
<< std::endl;
}
if (red_and_blue[Channel::Green])
std::cout << "bit set contains Green" << std::endl;
return 0;
}

32
example/Makefile Normal file
View File

@ -0,0 +1,32 @@
ifndef CXX
CXX := c++
endif
ifndef CXXFLAGS
CXXFLAGS := -std=c++11 -Wall -I .. -o
endif
SOURCES := $(wildcard *.cc)
BINARIES := $(SOURCES:.cc=.exe)
.PHONY : default
default : run
@:
.PHONY : all
all : $(BINARIES)
%.exe : %.cc ../*.h Makefile
$(CXX) $(CXXFLAGS) $@ $<
.PHONY : clean
clean :
rm -rf *.exe
.PHONY : run
run : all
@for BINARY in $(BINARIES) ; \
do \
echo ./$$BINARY ; \
./$$BINARY | sed -e "s/^/ /" ; \
done

111
pp_map_gen.py Executable file
View File

@ -0,0 +1,111 @@
#! /usr/bin/env python
# This file is part of Better Enums, released under the BSD 2-clause license.
# See LICENSE for details, or visit http://github.com/aantron/better-enums.
import os
import sys
class MultiLine(object):
def __init__(self, stream, indent = 4, columns = 80, initial_column = 0):
self._columns_left = columns - initial_column
self._indent = indent
self._columns = columns
self._stream = stream
def write(self, token, last = False):
break_line = False
if last:
if len(token) > self._columns_left:
break_line = True
else:
if len(token) > self._columns_left - 1:
break_line = True
if break_line:
print >> self._stream, ' ' * (self._columns_left - 1) + '\\'
self._stream.write(' ' * self._indent)
self._columns_left = self._columns - self._indent
token = token.lstrip()
self._stream.write(token)
self._columns_left -= len(token)
def generate(stream, filename, count, script):
print >> stream, '/// @file ' + filename
print >> stream, '/// @brief Preprocessor higher-order map macro.'
print >> stream, '///'
print >> stream, '/// This file was automatically generated by ' + script
print >> stream, ''
print >> stream, '#pragma once'
print >> stream, ''
print >> stream, '#ifndef _BETTER_ENUM_ENUM_PREPROCESSOR_MAP_H_'
print >> stream, '#define _BETTER_ENUM_ENUM_PREPROCESSOR_MAP_H_'
print >> stream, ''
print >> stream, '#define _ENUM_PP_MAP(macro, data, ...) \\'
print >> stream, ' _ENUM_PP_APPLY(_ENUM_PP_MAP_VAR_COUNT, ' + \
'_ENUM_PP_COUNT(__VA_ARGS__)) \\'
print >> stream, ' (macro, data, __VA_ARGS__)'
print >> stream, ''
print >> stream, '#define _ENUM_PP_MAP_VAR_COUNT(count) ' + \
'_ENUM_PP_MAP_ ## count'
print >> stream, ''
print >> stream, '#define _ENUM_PP_APPLY(macro, ...) macro(__VA_ARGS__)'
print >> stream, ''
print >> stream, '#define _ENUM_PP_MAP_1(macro, data, x) ' + \
'_ENUM_PP_APPLY(macro, data, x)'
for index in range(2, count + 1):
print >> stream, '#define _ENUM_PP_MAP_' + str(index) + \
'(macro, data, x, ...) ' + \
'_ENUM_PP_APPLY(macro, data, x), \\'
print >> stream, ' ' + \
'_ENUM_PP_MAP_' + str(index - 1) + \
'(macro, data, __VA_ARGS__)'
print >> stream, ''
pp_count_impl_prefix = '#define _ENUM_PP_COUNT_IMPL(_1,'
stream.write(pp_count_impl_prefix)
pp_count_impl = MultiLine(stream = stream, indent = 4,
initial_column = len(pp_count_impl_prefix))
for index in range(2, count + 1):
pp_count_impl.write(' _' + str(index) + ',')
pp_count_impl.write(' count,')
pp_count_impl.write(' ...)')
pp_count_impl.write(' count', last = True)
print >> stream, ''
print >> stream, ''
pp_count_prefix = \
'#define _ENUM_PP_COUNT(...) _ENUM_PP_COUNT_IMPL(__VA_ARGS__,'
stream.write(pp_count_prefix)
pp_count = MultiLine(stream = stream, indent = 4,
initial_column = len(pp_count_prefix))
for index in range(0, count - 1):
pp_count.write(' ' + str(count - index) + ',')
pp_count.write(' 1)', last = True)
print >> stream, ''
print >> stream, ''
print >> stream, '#endif // #ifndef _BETTER_ENUM_ENUM_PREPROCESSOR_MAP_H_'
if __name__ == '__main__':
if len(sys.argv) != 3:
print >> sys.stderr, 'Usage: ' + sys.argv[0] + ' FILE COUNT'
print >> sys.stderr, ''
print >> sys.stderr, 'Prints map macro definition to FILE.'
sys.exit(1)
output_file = open(sys.argv[1], "w")
try:
generate(output_file, sys.argv[1], int(sys.argv[2]),
os.path.basename(sys.argv[0]))
finally:
output_file.close()
sys.exit(0)

45
test/Makefile Normal file
View File

@ -0,0 +1,45 @@
ifndef CXX
CXX := c++
endif
ifndef CXXFLAGS
CXXFLAGS := -std=c++11 -Wall -I .. -o
endif
CXXTEST_H := cxxtest/tests.h
CXXTEST_SRC := $(CXXTEST_H:.h=.cc)
CXXTEST_BIN := $(CXXTEST_H:.h=.exe)
LINK_BIN := link/link.exe
PERFORMANCE_SRC := $(wildcard performance/*.cc)
PERFORMANCE_BIN := $(PERFORMANCE_SRC:.cc=.exe)
.PHONY : default
default : run
@:
$(CXXTEST_SRC) : $(CXXTEST_H) Makefile
cxxtestgen --error-printer -o $@ $<
$(CXXTEST_BIN) : $(CXXTEST_SRC) ../*.h Makefile
$(CXX) $(CXXFLAGS) $@ $<
@echo Passed `grep 'static_assert_1' $(CXXTEST_H) | wc -l` static assertions
$(LINK_BIN) : link/*.h link/*.cc ../*.h Makefile
$(CXX) $(CXXFLAGS) $@ link/*.cc
$(PERFORMANCE_BIN) : %.exe : %.cc
@echo $<
@/usr/bin/time -p $(CXX) $(CXXFLAGS) $@ $<
@rm $@
.PHONY : run
run : $(CXXTEST_BIN) $(LINK_BIN) $(PERFORMANCE_BIN)
./$(CXXTEST_BIN)
./$(LINK_BIN)
.PHONY : clean
clean :
rm -f $(CXXTEST_SRC)
find -E . -regex '.*\.exe' | xargs rm -f

200
test/cxxtest/tests.h Normal file
View File

@ -0,0 +1,200 @@
#include <stdexcept>
#include <type_traits>
#include <cxxtest/TestSuite.h>
#include <enum.h>
#define static_assert_1(e) static_assert(e, #e)
ENUM(Channel, short, Red, Green, Blue);
ENUM(Depth, short, HighColor = 40, TrueColor = 20);
ENUM(Compression, short, None, Huffman, Default = Huffman);
// Type properties.
static_assert_1(std::is_class<Channel>());
static_assert_1(std::is_trivial<Channel>());
static_assert_1(std::is_standard_layout<Channel>());
static_assert_1(std::is_pod<Channel>());
static_assert_1(std::is_literal_type<Channel>());
// Member type properties and identities.
static_assert_1(std::is_integral<Channel::_Integral>());
static_assert_1(std::is_enum<Channel::_Enumerated>());
static_assert_1((std::is_same<short, Channel::_Integral>()));
static_assert_1((std::is_same<
short, std::underlying_type<Channel::_Enumerated>::type>()));
static_assert_1(!(std::is_same<int, Channel::_Integral>()));
static_assert_1(!(std::is_same<
int, std::underlying_type<Channel::_Enumerated>::type>()));
static_assert_1(sizeof(Channel) == sizeof(short));
static_assert_1(alignof(Channel) == alignof(short));
static_assert_1((std::is_same<decltype(Channel::Red), Channel::_Enumerated>()));
// Supported constructors.
static_assert_1(!std::is_default_constructible<Channel>());
#ifdef __clang__
static_assert_1(std::is_trivially_copyable<Channel>());
#endif
static_assert_1((std::is_constructible<Channel, Channel::_Enumerated>()));
static_assert_1(!(std::is_constructible<Channel, Channel::_Integral>()));
static_assert_1(!(std::is_constructible<Channel, Depth>()));
// Intended implicit conversions.
static_assert_1((std::is_convertible<Channel::_Enumerated, Channel>()));
static_assert_1(!(std::is_convertible<Channel::_Integral, Channel>()));
static_assert_1(!(std::is_convertible<Depth, Channel>()));
static_assert_1(!(std::is_convertible<Channel, Depth>()));
// Regrettable implicit conversions.
static_assert_1((std::is_convertible<Channel, Channel::_Enumerated>()));
static_assert_1((std::is_convertible<Channel, Channel::_Integral>()));
// Range properties.
static_assert_1(Channel::_size == 3);
static_assert_1(Depth::_size == 2);
static_assert_1(Channel::_span == 3);
static_assert_1(Depth::_span == 21);
static_assert_1(Channel::_first == Channel::Red);
static_assert_1(Channel::_last == Channel::Blue);
static_assert_1(Depth::_first == Depth::HighColor);
static_assert_1(Depth::_last == Depth::TrueColor);
static_assert_1(Channel::_min == Channel::Red);
static_assert_1(Channel::_max == Channel::Blue);
static_assert_1(Depth::_min == Depth::TrueColor);
static_assert_1(Depth::_max == Depth::HighColor);
// Constant values.
static_assert_1((+Channel::Red).to_integral() == 0);
static_assert_1((+Channel::Green).to_integral() == 1);
static_assert_1((+Channel::Blue).to_integral() == 2);
static_assert_1((+Depth::HighColor).to_integral() == 40);
static_assert_1((+Depth::TrueColor).to_integral() == 20);
// Integral conversions.
static_assert_1(Channel::_from_integral(1) == Channel::Green);
static_assert_1(Channel::_from_integral(1) != Channel::Blue);
static_assert_1(Channel::_from_integral_unchecked(1) == Channel::Green);
static_assert_1(Channel::_from_integral_unchecked(1) != Channel::Blue);
static_assert_1(Channel::_is_valid((Channel::_Integral)0));
static_assert_1(Channel::_is_valid(1));
static_assert_1(Channel::_is_valid(2));
static_assert_1(!Channel::_is_valid(3));
// String conversions.
static_assert_1(Channel::_from_string("Green") == Channel::Green);
static_assert_1(Channel::_from_string("Green") != Channel::Blue);
static_assert_1(Channel::_from_string("Blue") == Channel::Blue);
static_assert_1(Channel::_from_string("Blue") != Channel::Green);
static_assert_1(Channel::_from_string_nocase("green") == Channel::Green);
static_assert_1(Channel::_from_string_nocase("green") != Channel::Blue);
static_assert_1(Channel::_from_string_nocase("blue") == Channel::Blue);
static_assert_1(Channel::_from_string_nocase("blue") != Channel::Green);
static_assert_1(Channel::_is_valid("Green"));
static_assert_1(!Channel::_is_valid("green"));
static_assert_1(Channel::_is_valid_nocase("green"));
static_assert_1(!Channel::_is_valid_nocase("greeen"));
// Iterables.
static_assert_1(Channel::_values.size() == Channel::_size);
static_assert_1(*Channel::_values.begin() == Channel::_first);
static_assert_1(Channel::_names.size() == Channel::_size);
// Aliases.
static_assert_1(Compression::Default == Compression::Huffman);
// Run-time testing.
class EnumTests : public CxxTest::TestSuite {
public:
void test_bad_integral_conversions()
{
TS_ASSERT_THROWS(Channel::_from_integral(3), std::runtime_error);
TS_ASSERT_THROWS_NOTHING(Channel::_from_integral_unchecked(3));
}
void test_string_conversions()
{
TS_ASSERT_EQUALS(strcmp((+Channel::Green).to_string(), "Green"), 0);
TS_ASSERT_EQUALS(strcmp((+Channel::Blue).to_string(), "Blue"), 0);
TS_ASSERT_THROWS(Channel::_from_string("green"), std::runtime_error);
TS_ASSERT_THROWS(Channel::_from_string_nocase("a"), std::runtime_error);
}
void test_value_iterable()
{
auto value_iterator = Channel::_values.begin();
TS_ASSERT_EQUALS(*value_iterator, Channel::Red);
TS_ASSERT_DIFFERS(value_iterator, Channel::_values.end());
++value_iterator;
TS_ASSERT_EQUALS(*value_iterator, Channel::Green);
TS_ASSERT_DIFFERS(value_iterator, Channel::_values.end());
++value_iterator;
TS_ASSERT_EQUALS(*value_iterator, Channel::Blue);
TS_ASSERT_DIFFERS(value_iterator, Channel::_values.end());
++value_iterator;
TS_ASSERT_EQUALS(value_iterator, Channel::_values.end());
}
void test_name_iterable()
{
auto name_iterator = Channel::_names.begin();
TS_ASSERT_EQUALS(strcmp(*name_iterator, "Red"), 0);
TS_ASSERT_DIFFERS(name_iterator, Channel::_names.end());
++name_iterator;
TS_ASSERT_EQUALS(strcmp(*name_iterator, "Green"), 0);
TS_ASSERT_DIFFERS(name_iterator, Channel::_names.end());
++name_iterator;
TS_ASSERT_EQUALS(strcmp(*name_iterator, "Blue"), 0);
TS_ASSERT_DIFFERS(name_iterator, Channel::_names.end());
++name_iterator;
TS_ASSERT_EQUALS(name_iterator, Channel::_names.end());
}
void test_type_name()
{
TS_ASSERT_EQUALS(strcmp(Channel::_name, "Channel"), 0);
TS_ASSERT_EQUALS(strcmp(Depth::_name, "Depth"), 0);
TS_ASSERT_EQUALS(strcmp(Compression::_name, "Compression"), 0);
}
};

7
test/link/helper.cc Normal file
View File

@ -0,0 +1,7 @@
#include <iostream>
#include "shared.h"
void print(Channel channel)
{
std::cout << Channel::_name << "::" << channel.to_string() << std::endl;
}

8
test/link/helper.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef _HELPER_H_
#define _HELPER_H_
#include "shared.h"
void print(Channel channel);
#endif // #ifndef _HELPER_H_

9
test/link/main.cc Normal file
View File

@ -0,0 +1,9 @@
#include "shared.h"
#include "helper.h"
int main()
{
print(Channel::Red);
return 0;
}

8
test/link/shared.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef _SHARED_H_
#define _SHARED_H_
#include <enum.h>
ENUM(Channel, int, Red, Green, Blue);
#endif // #ifndef _SHARED_H_

View File

@ -0,0 +1,4 @@
int main()
{
return 0;
}

View File

@ -0,0 +1,6 @@
#include "empty.h"
int main()
{
return 0;
}

View File

@ -0,0 +1,6 @@
#include <enum.h>
int main()
{
return 0;
}

View File

@ -0,0 +1,229 @@
#include <enum.h>
ENUM(Channel, int,
Red, Green, Blue, Cyan, Magenta, Yellow, Black, Hue, Saturation, Value);
ENUM(Direction, int,
North, East, South, West, NorthEast, SouthEast, SouthWest, NorthWest,
NorthNorthEast, EastNorthEast, EastSouthEast, SouthSouthEast,
SouthSouthWest, WestSouthWest, WestNorthWest, NorthNorthWest);
ENUM(ASTNode, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(State, int,
Attacking, Defending, Searching, Pursuing, Hungry, Fleeing, Confused,
Healing, Stunned);
ENUM(APIMethod, int,
ReadPost, WritePost, PollPost, ReadImage, WriteImage, PollImage, ReadKey,
WriteKey, PollKey, ReadUser, WriteUser, PollUser, ReadOrganization,
WriteOrganization, PollOrganization, ReadGroup, WriteGroup, PollGroup,
ReadProject, WriteProject, PollProject, ReadComment, WriteComment,
PollComment, ReadPermission, WritePermission, PollPermission, ReadOwner,
WriteOwner, PollOwner, ReadProposal, WriteProposal, PollProposal,
ReadHistory, WriteHistory, PollHistory);
ENUM(Region, int,
EasterEurope, CentralEurope, WesternEurope, Mediterranean, NorthAfrica,
MiddleEast, MiddleEastNorthAfrica, GreaterPersia, Balkans, Scandinavia,
NorhernEurope, BritishIsles, LatinEurope, Iberia, LowCountries, Baltics,
Yugoslavia, Caucasus, VolgaBasin, Urals, CentralAsia, Siberia,
RussianFarEast, EastAsia, SoutheastAsia, Indochina, SouthAsia,
IndianSubcontinent, Desi = IndianSubcontinent, Asia, Australasia, Oceania,
Micronesia, Polynesia, JapaneseIslands, Tibet, ArabianPeninsula,
HornOfAfrica, NearEast, AlSham, EastAfrica, NileBasin, Palestine, Levant,
Anatolia, AegeanSea, GreatSteppe, CongoBasin, SouthAfrica, WestAfrica,
Sahara, WestSahara, NorthwestTerritory, YukonAlaska, Quebec, NewEngland,
DeepSouth, PacificCoast, BajaCalifornia, Yucatan, NorthAmerica,
CentralAmerica, LatinAmerica, SpanishAmerica, AmazonBasin,
MississippiBasin, RioDeLaPlata, Andes, TierraDelFuego, Galapagos,
GranColombia);
int main()
{
return 0;
}
ENUM(ASTNode0, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode1, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode2, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode3, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode4, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode5, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode6, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode7, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode8, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode9, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode10, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode11, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode12, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode13, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode14, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode15, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode16, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode17, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode18, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode19, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode20, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode21, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode22, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode23, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode24, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode25, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode26, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode27, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode28, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);
ENUM(ASTNode29, int,
IntegerLiteral, StringLiteral, CharacterLiteral, Variable, UnaryOperation,
BinaryOperation, ApplicationExpression, Abstraction, LetBinding,
CaseExpression, Pattern, Signature, Module, Functor, TypeVariable,
BasicType, ArrowType, VariantTypeConstant);

View File

@ -0,0 +1,6 @@
#include <iostream>
int main()
{
return 0;
}

0
test/performance/empty.h Normal file
View File