better-enums icon indicating copy to clipboard operation
better-enums copied to clipboard

Debugger friendly? Inheritance?

Open rosetter opened this issue 7 years ago • 3 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 avatar Oct 03 '18 03:10 rosetter

@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?

aantron avatar Oct 03 '18 17:10 aantron

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<EnumName> 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! ;)

rosetter avatar Oct 03 '18 23:10 rosetter

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 :/

aantron avatar Oct 04 '18 16:10 aantron