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