mirror of
https://github.com/aantron/better-enums.git
synced 2025-12-06 08:46:42 +08:00
Initial release.
This commit is contained in:
parent
f54960590a
commit
dd606fd450
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.h linguist-language=C++
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1,5 @@
|
||||
*.pyc
|
||||
*.exe
|
||||
scratch/
|
||||
doc-publish/
|
||||
test/*.cc
|
||||
|
||||
23
LICENSE
Normal file
23
LICENSE
Normal 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
112
README.md
Normal 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
940
doc/index.html
Normal 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 <enum.h>
|
||||
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&)
|
||||
<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&)
|
||||
<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&)
|
||||
<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&)
|
||||
<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&)
|
||||
<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&)
|
||||
<span>const</span>
|
||||
</h3>
|
||||
|
||||
<h3>
|
||||
<span>member constexpr</span> bool operator >=(_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 © 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
534
enum.h
Normal 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
571
enum_preprocessor_map.h
Normal 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
98
example/1-basic.cc
Normal 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
40
example/2-iterate.cc
Normal 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
38
example/3-switch.cc
Normal 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
92
example/4-constexpr.cc
Normal 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
64
example/5-containers.cc
Normal 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
55
example/6-traits.cc
Normal 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
33
example/7-bitset.cc
Normal 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
32
example/Makefile
Normal 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
111
pp_map_gen.py
Executable 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
45
test/Makefile
Normal 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
200
test/cxxtest/tests.h
Normal 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
7
test/link/helper.cc
Normal 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
8
test/link/helper.h
Normal 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
9
test/link/main.cc
Normal 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
8
test/link/shared.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef _SHARED_H_
|
||||
#define _SHARED_H_
|
||||
|
||||
#include <enum.h>
|
||||
|
||||
ENUM(Channel, int, Red, Green, Blue);
|
||||
|
||||
#endif // #ifndef _SHARED_H_
|
||||
4
test/performance/1-simple.cc
Normal file
4
test/performance/1-simple.cc
Normal file
@ -0,0 +1,4 @@
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
6
test/performance/2-include_empty.cc
Normal file
6
test/performance/2-include_empty.cc
Normal file
@ -0,0 +1,6 @@
|
||||
#include "empty.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
6
test/performance/3-only_include_enum.cc
Normal file
6
test/performance/3-only_include_enum.cc
Normal file
@ -0,0 +1,6 @@
|
||||
#include <enum.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
229
test/performance/4-declare_enums.cc
Normal file
229
test/performance/4-declare_enums.cc
Normal 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);
|
||||
6
test/performance/5-iostream.cc
Normal file
6
test/performance/5-iostream.cc
Normal file
@ -0,0 +1,6 @@
|
||||
#include <iostream>
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
0
test/performance/empty.h
Normal file
0
test/performance/empty.h
Normal file
Loading…
x
Reference in New Issue
Block a user