On Saturday, April 12, 2014 12:43:32 Andrei Alexandrescu wrote: > On 4/12/14, 5:59 AM, Jonathan M Davis wrote: > > If the enum > > doesn't enumerate all of the values, then you're clearly going to be using > > other values with it, meaning that any restrictions on setting a variable > > to those other values is going to be a problem (as is currently the case > > with enums - assignment and initialization are protected against > > non-enumerated values). You'd just end up with a enum type which is > > effectively an alias for the enum's base type except that assigning it > > non-enumerated values requires casting, and you can overload a function > > on the enumerated values vs the non- enumerated ones (or at least, > > non-enumerated ones which aren't cast to the enum type) by overloading a > > function on the enum type and its base type - which would be highly > > bug-prone IMHO. > > Sorry, your speculations are mistaken. The pattern works well and we've > been using it repeatedly and with good results since C++ introduced > "enum class".
I would have expected that all of the required casting would be annoying and that overloading between the enum and its base type would be error-prone, because all you have to do is forget to cast when passing a literal, and you end up with the wrong overload being called. But I guess if you view casting to the enum type like a constructor, then it makes sense, and apparently, it's working for you. Regardless, I'd never use an enum to partially enumerate values for a type, because I think that that violates the very concept of what an enumeration is. And I expect that enums get used so frequently in other ways primarily due to the fact that C's enums are so weakly typed. I'd use a struct for any case where I wanted a new type which didn't have a full enumeration of its values, and any constants would probably just be static variables or manifest constants on the struct. So, I'm not at all interested in having D's enum not fully protect against having a variable of that enum type end up becoming a non-enumerated value, and I don't at all value the ability to have enums which aren't intended to enumerate all of their values. But clearly, not everyone agrees on that. So, if we add final enum, and it properly protects against any operation on a variable of that enum type ever becoming a non-enumerated value without a cast, and it works with final switch, then great. I won't like what non-final enums do, and I'll never use them, but at least then we can have non-buggy behavior for enums which are intended to enumerate all of their values. As it stands, I think that C++'s enum class are better than D's enums, because they actually protect against any operations (other than casts) giving the enum a non-enumerated value, and Ds enums don't - though enum classes arguably go a bit far, because they don't provide implicit conversions to their base type, and you have to overload any operators on the type that you want to use. But I'd still rather have that than have to worry about enum variables becoming non-enumerated values like we currently have to worry about in D - and features like final switch just make it that much worse when an enum variable ends up with a non-enumerated value. - Jonathan M Davis
