mirror of
https://github.com/aantron/better-enums.git
synced 2025-12-06 16:56:42 +08:00
The documentation is now generated from markdown. Samples are generated from the tutorial pages. Testing is done by a Python script which runs the tests for a large number of compilers. This version is not very developer-friendly - the Python scripts need ways of limiting what compilers they try to run. If you don't have 15 compilers installed, you won't be able to run the tests in this commit. Fix coming soon.
143 lines
4.3 KiB
C++
143 lines
4.3 KiB
C++
// This file was generated automatically
|
|
|
|
// Conversions
|
|
//
|
|
// Let's begin by including enum.h and declaring our enum:
|
|
|
|
#include <cassert>
|
|
#include <iostream>
|
|
|
|
#include <enum.h>
|
|
|
|
ENUM(Channel, int, Cyan = 1, Magenta, Yellow, Black)
|
|
|
|
// We now have an int-sized enum with four constants.
|
|
//
|
|
// 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.
|
|
//
|
|
// Strings
|
|
//
|
|
// There are three functions:
|
|
//
|
|
// 1. ._to_string
|
|
// 2. ::_from_string
|
|
// 3. ::_from_string_nothrow
|
|
|
|
int main()
|
|
{
|
|
Channel channel = Channel::Cyan;
|
|
std::cout << channel._to_string() << " ";
|
|
|
|
// As you'd expect, the code above prints "Cyan".
|
|
//
|
|
// If channel is invalid — for example, if you simply cast the number "42"
|
|
// to Channel — then the result of to_string is undefined.
|
|
|
|
channel = Channel::_from_string("Magenta");
|
|
std::cout << channel._to_string() << " ";
|
|
|
|
// This is also straightforward. If you pass a string which is not the name of a
|
|
// declared value, _from_string throws std::runtime_error.
|
|
// If you don't want an exception, there is _from_string_nothrow:
|
|
|
|
better_enums::optional<Channel> maybe_channel =
|
|
Channel::_from_string_nothrow("Yellow");
|
|
|
|
if (!maybe_channel)
|
|
std::cout << "error";
|
|
else
|
|
std::cout << maybe_channel->_to_string() << " ";
|
|
|
|
// 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">boost::optional</a>
|
|
// or the proposed <a
|
|
// href="http://en.cppreference.com/w/cpp/experimental/optional">std::optional</a>.
|
|
//
|
|
// What that means for the above code is:
|
|
//
|
|
// 1. if the conversion succeeds, maybe_channel converts to true and
|
|
// *maybe_channel is the converted value of type Channel,
|
|
// 2. if the conversion fails, maybe_channel converts to false.
|
|
//
|
|
// In $cxx11, you can use auto to avoid writing out the optional type:
|
|
//
|
|
// auto maybe_channel = Channel::_from_string_nothrow("Yellow");
|
|
// if (!maybe_channel)
|
|
// std::cout << "error";
|
|
// else
|
|
// std::cout << maybe_channel->_to_string() << " ";
|
|
//
|
|
// Case-insensitive strings
|
|
//
|
|
// The "_nocase" string conversions follow the same pattern, except for the lack
|
|
// of a "to_string_nocase".
|
|
//
|
|
// 1. ::_from_string_nocase
|
|
// 2. ::_from_string_nocase_nothrow
|
|
|
|
channel = Channel::_from_string_nocase("cYaN");
|
|
std::cout << channel._to_string() << " ";
|
|
|
|
maybe_channel = Channel::_from_string_nocase_nothrow("rEeD");
|
|
assert(!maybe_channel);
|
|
|
|
// Integers
|
|
//
|
|
// And, it is similar with the <em>representation type</em> int:
|
|
//
|
|
// 1. ._to_integral
|
|
// 2. ::_from_integral
|
|
// 3. ::_from_integral_nothrow
|
|
// 4. ::_from_integral_unchecked
|
|
|
|
channel = Channel::Cyan;
|
|
std::cout << channel._to_integral() << " ";
|
|
|
|
channel = Channel::_from_integral(2);
|
|
std::cout << channel._to_string() << " ";
|
|
|
|
maybe_channel = Channel::_from_integral_nothrow(0);
|
|
assert(!maybe_channel);
|
|
|
|
// That prints "1 Magenta".
|
|
//
|
|
// _from_integral_unchecked is a no-op unchecked cast of integers to enums, so
|
|
// use it carefully.
|
|
|
|
channel = Channel::_from_integral_unchecked(0);
|
|
// Invalid - better not to try converting it to string!
|
|
|
|
// Aside
|
|
//
|
|
// You have certainly noticed that all the method names begin with underscores.
|
|
// This is because they share scope with the enum constants that you declare.
|
|
// Better Enums is trying to stay out of your way by using a prefix.
|
|
//
|
|
// Validity checking
|
|
//
|
|
// For completeness, Better Enums also provides three validity checking
|
|
// functions, one for each of the groups of conversions — string,
|
|
// case-insensitive string, and integer:
|
|
|
|
assert(Channel::_is_valid(3));
|
|
assert(Channel::_is_valid("Magenta"));
|
|
assert(Channel::_is_valid_nocase("cYaN"));
|
|
|
|
// Almost done.
|
|
//
|
|
// There is one unfortunate wrinkle. You cannot convert a literal constant such
|
|
// as Channel::Cyan directly to, for example, a string. You have to prefix it
|
|
// with +:
|
|
|
|
std::cout << (+Channel::Cyan)._to_string();
|
|
|
|
// This is due to some type gymnastics in the implementation of Better Enums.
|
|
// The <a>Reference</a> section has a full explanation.
|
|
// This concludes the first tutorial!
|
|
|
|
std::cout << std::endl;
|
|
return 0;
|
|
}
|