Anton Bachin 6278793a0b Added workarounds for VC2008.
VC2008 has two quirks. It generates linking errors if a copy
constructor is not explicitly defined on a Better Enum, and it has a
buggy interaction between the ternary operator and throw. This change
detects VC2008 and generates alternative code for that compiler.

Having an explicitly-defined copy constructor in a literal type appears
to cause an internal compiler error in g++4.7, and causes a spurious
compilation failure in g++4.8. For this reason, the copy constructor
generation is conditioned on the compiler.

The replacement code for the ternary operator is also generated
conditionally, because it uses an if-statement. The normal code has to
compile in a constexpr context, and so has to use the ternary operator
instead of the if-statement.

Resolves #6.
2015-07-07 11:22:40 -05:00
doc Support for testing in AppVeyor. 2015-07-01 23:58:23 -05:00
example Made it easier to generate offline documentation. 2015-06-27 13:56:27 -05:00
script Eliminated underscored internal macro names. 2015-06-05 19:20:18 -05:00
test Updated CONTRIBUTING.md and related information. 2015-07-02 16:56:33 -05:00
.gitattributes Complete documentation and testing overhaul. 2015-05-27 09:58:34 -05:00
.gitignore Switched to CMake for building tests. 2015-07-01 15:18:48 -05:00
.travis.yml Added support for testing in Travis. 2015-07-02 15:51:01 -05:00
appveyor.yml Sped up the AppVeyor build. 2015-07-02 18:17:06 -05:00
CONTRIBUTING.md Sped up the AppVeyor build. 2015-07-02 18:17:06 -05:00
CONTRIBUTORS Updated CONTRIBUTING.md and related information. 2015-07-02 16:56:33 -05:00
enum.h Added workarounds for VC2008. 2015-07-07 11:22:40 -05:00
LICENSE Made it easier to generate offline documentation. 2015-06-27 13:56:27 -05:00
README.md Updated README. 2015-06-20 17:00:49 -05:00

Better Enums

Reflective compile-time C++ enum library with clean syntax, in a single header file. For example:

#include <enum.h>
ENUM(Channel, uint8_t, Red = 1, Green, Blue)

defines a type Channel. You can then do natural things such as:

Channel channel = Channel::Green;

channel._to_string();           // Results in the string "Green"
Channel::_from_string("Red");   // Results in Channel::Red

Channel::_from_integral(3);     // Checked cast, Channel::Blue

Channel::_size;                 // Number of channels (3)
Channel::_values()[0];          // Get the first channel

for (Channel channel : Channel::_values()) {
    process(channel);           // Iterate over all channels
}

// Automatic case checking, just as with a built-in enum.
switch (channel) {
    case Channel::Red:   break;
    case Channel::Green: break;
    case Channel::Blue:  break;
}

...and more. You can try it live here.

In C++11, everything is available at compile time. You can convert your enums, loop over them, find their max, statically enforce conventions, and pass along the results as template arguments or to constexpr functions. All the reflection is available for your metaprogramming needs.

The interface is the same for C++98 — you just have to use most of it at run time only. This library does provide scoped and sized enums, something not built into C++98.

See the project page for full documentation.

Installation

Simply add enum.h to your project — that's it.

Then, include it and use the ENUM macro. Your compiler will generate the rich enums that are missing from standard C++.

Additional features

  • No dependencies and no external build tools. Uses only standard C++, though, for C++98, variadic macro support is required.
  • Supported and tested on clang, gcc, and msvc.
  • Fast compilation. You have to declare a few dozen enums to slow down your compiler as much as just including iostream does.
  • Use any initializers and sparse ranges, just like with a built-in enum.
  • Guaranteed size and alignment — you choose the representation type.
  • Stream operators supported.
  • Does not use the heap and can be compiled with exceptions disabled, for use in minimal freestanding environments.
  • The underlying type can be an object type.

Limitations

The biggest limitation is that the ENUM macro can't be used inside a class. This seems difficult to remove. There is a workaround with typedef (or using):

ENUM(UniquePrefix_Color, uint8_t, Red, Green, Blue)

struct triplet {
    typedef UniquePrefix_Color      Color;
    Color                           r, g, b;
};

triplet::Color  color;

You can, however, use ENUM inside a namespace.

Contact

Don't hesitate to contact me about features or bugs: antonbachin@yahoo.com, Twitter @better_enums, or open an issue on GitHub.

License and history

Better Enums is released under the BSD 2-clause license. See LICENSE.

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.