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