aantron / better-enums

C++ compile-time enum to string, iteration, in a single header file

Home Page:http://aantron.github.io/better-enums

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Debugger friendly? Inheritance?

rosetter opened this issue · comments

Hi.. fantastic work! Very impressive. :)

Just a couple of unsolicited thoughts:

  1. I stumbled onto this project looking for a way to add methods to enums. So for example I'd like to be able to say:
enum Fruit { Apple, Orange };
Fruit f = Orange;
if (f.isRed()) { ... }

It would be wonderful if I could do something like:

struct Fruit {
   BETTER_ENUM_BODY(Fruit, uint8_t, Apple, Orange)
   bool isRed() const { return _value == Apple; }
}

Looking briefly at the code makes me think this would be difficult. :(

  1. The underlying storage seems to be not an enum but an integer type. So when I inspect an instance in a debugger I get an integer instead of a nice, readable string. To me this is best reason to use an enum in the first place, so it's a deal breaker.

I think I'll play around with modifying your earlier, much simpler version on CodeProject. :)

Again, great work!

@rosetter IIRC it's possible to derive a struct from one of these enums, which will then allow you to add methods.

For #2, is your debugger interpreting enum integral values and turning them back into strings?

Subclassing was my first thought, but I'd need to repeat the constructors and conversion operator in each derived class, which is unappealing. Also _value is then declared in the base class, not the user-facing class, which some debuggers hide with an extra level of hierarchy.

The debugger shows an integral value for the _value member in my example above because it is defined as _underlying (uint8_t), not _enum.

FWIW, I ended up modifying your simpler CodeProject version:

  1. I changed the type of _value to _enum, not _underlying to solve problem 2. Which may break older compilers.
  2. I created a second "ENUM_WITH_EXTENSION" macro that takes an "Extension" parameter. The enum class then derives from Extension so I can use the CRTP to extend the enum.

So now I can say:

template <typename T>
struct FruitExtension : public Crtp<T>
{
    bool isRed() const { return this->asT() == T::Apple; }
};

ENUM_WITH_EXTENSION(Fruit, uint8_t, FruitExtension, Apple, Orange)

Where Crtp is defined elsewhere as:

template <typename T>
struct Crtp
{
    constexpr T& asT() { return static_cast<T&>(*this); }
    constexpr T const& asT() const { return static_cast<T const&>(*this); }
};

This makes my original desired syntax possible.. whew.

This has been a fun vacation in Meta-Uber-Land, but now it's time to get back to work! ;)

Great, I'm glad this worked. We may be able to define _value as the enum type once we finally drop support for C++98. I want to do this, but I haven't had the time to edit enum.h lately :/