better-enums/example/2-conversions.cc
Anton Bachin e1e237a4ea Renamed top-level macro ENUM to BETTER_ENUM.
To reduce name clashes.

Fixes #11.
2015-10-04 11:03:08 -05:00

138 lines
3.8 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>
BETTER_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 optional value, in the style of boost::optional or the
// proposed std::optional.
//
// 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 C++11, 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 representation type 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!
// 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 reference has a full explanation.
std::cout << std::endl;
return 0;
}