Hah, already realized I made a silly mistake. The current implementation uses variable templates and therefore isn't 11 compatible of course. The template variables can be optionally compiled for C++14, and C++11 can use static members of template structs. On Wed, Jan 17, 2018 at 3:21 PM, Nir Friedman <quicknir@gmail.com> wrote:
Hello,
I recently needed a reflective enum for work (that is an enum where you can programmatically convert to and from strings, know how many enumerators there are, and iterate over all enumerators). I looked online but I didn't find anything that met my requirements. I was surprised that there wasn't one in Boost. So I'd like to see if there is interest; I wrote an implementation that I think has several nice features.
The most polished existing smart enum implementation I could find was http://aantron.github.io/better-enums/. However, the enum implemented there is not a true enum; it uses a nested member of a class kind of approach. So for example, the is_enum type trait will not recognize is as an enum. You cannot use it as a non-type template parameter.
I strongly think that a good generic smart enum macro should generate the exact "vanilla" enum (or enum class) declaration. My library's syntax looks like this:
WISE_ENUM(Foo, BAR, (BAZ, 3))
This generates, among other things, exactly:
enum Foo { BAR, BAZ=3};
I intend this as an explicit guarantee of the library that the programmer can count on. That way when Foo is used for things unrelating to reflection, the developer can be confident that there will not be any surprises. Beyond compatability with C++ facilities for enums, and minimizing surprise, another advantage of this approach is that it's guaranteed to be backwards compatible. An existing codebase with an existing enum/enum class can switch to this smart enum with very high confidence that existing code will continue to work as before.
The WISE_ENUM macro, beyond generating the vanilla enum, also generates a switch-case function for to-string conversion (for maximal efficiency), and finally it generates a constexpr function that returns a std::array<std::pair<const char*, Foo>> listing all of the arrays and their string descriptions. This constexpr function, which is found via ADL, allows writing a sequence of (constexpr) variables and functions providing the rest of the desired functionality. Usage looks like this:
std::cerr << "My enum's size is : " << wise_enum::size<Foo> // this is constexpr template variable auto x = wise_enum::from_string<Foo>("BAR").value(); // from_string returns an optional auto y = wise_enum::to_string(x); // y is string literal, no heap allocation
My implementation (POC level) is here: https://github.com/ quicknir/wise_enum. I don't yet have separate macros to cover enum/enum class/explicit/implicit backing type combinations. It's only about 100 lines of code, leaning heavily on BOOST_PP to do the heavy lifting. It requires variadic macros, and can probably target C++11 (if it doesn't already). I probably need to "comma harden" the macros for bizarre stuff like WISE_ENUM(Foo, (BAR, my_func<3,4>())).
It has the limitation that the macro cannot be used inside a class (this is hard to workaround for reflective macros). It's also unclear how repeated enumeration values would be handled (enum Foo { BAR = 1, BAZ = 1}). As it stands this will cause a compilation failure in the generated switch case of the to_string function. Can discuss more in subsequent emails.
One suggested feature is an is_contiguous trait. Another reasonable bit of functionality might be an is_wise_enum trait. Version 2 of this library could target enum sets.
Although it's not fancy, I think this nicely covers a piece of functionality I often need, and it does so avoiding any downside compared to using a simple enum (beyond having to use macros). Hope other people will agree!
Cheers,
Nir