On 9/8/13 8:08, Andrej Mitrovic wrote:
I've recently ran into a bug that was very hard to track down for me.
I've had a good set of unittests, but I kept getting the wrong results
out of my functions, which was very bizarre.

To boil it down, when you introduce a member in an enum which
initializes itself to another member of that enum, the next member
after it will be initialized to + 1 of the previous member. So:

enum E
{
     a,
     b = a,
     c
}

Here, a equals 0, b equals 0 as well, and c equals b + 1, so it's 1.
There's nothing problematic here.

The real problem appears when you need to make sure each member is
unique, except for any members which are either convenience members or
are deprecated members (there's no "deprecated" member feature
yet[2]).

Here's an example:

enum MouseAction
{
     ///
     press,

     ///
     release,

     /** Convenience - equal to $(D press). */
     click = press,

     ///
     double_click,
}

Notice how introducing the convenience member has re-set the enum
initializer counter, meaning double_click will be equal to (click +
1), which is really (press + 1), which becomes (1). But (1) is also
the intializer for "release", so by mistake I made "double_click"
equal "release", and hence my bug.

So to work around this, I thought about introducing an alias feature to enums:

enum MouseAction
{
     press,

     release,

     alias click = press,  // does not reset the counter!

     double_click,  // equals release + 1
}

The alias member would not re-set the counter and instead the next
non-alias member would initialize itself to the previous non-alias
member + 1.

This would also lend itself well with the "deprecated" keyword, where
we could add deprecated aliases for old enum members when we want to
rename the members. For example, if you want to rename a Phobos enum
you can currently do :

enum SpanMode
{
     shallow,
     deep,
     depth = deep;  /// $(RED Deprecated, please use .deep)
     breadth,
}

I won't deny the possibility of human error here, but I don't think it's worth complicating the language for this case. It's easily fixed by putting the 'alias' after the 'good' enum value.

The case for 'deprecate' is much stronger, though. It's impossible to deprecate enum values now.

Reply via email to