Enumeration relying on integer boolean conversion
In my compiler project, I have an enumeration that goes like
enum Result {
No,
Maybe,
Yes
};
I have put No
explicitly at the first position, so that i can rely on the boolean evaluation to false
. If my compiler is not sure about something, and has to wait开发者_StackOverflow for facts until runtime, its analysis functions will return Maybe
. Used like
if(!typesEqual(t1, t2)) {
diagnose(types_unequal) << t1 << t2;
}
I wonder whether you or your company considers it bad style not to compare to No
explicitly
if(typesEqual(t1, t2) == No) { /* ... */ }
Comparing explicitly seems wordy to me, but relying on the implicit boolean conversion somehow makes me feel guilty. Have you had that feeling before, and how have you dealt with it?
I'd feel guilty about it as well, because from reading the code above what would you expect the boolean typesEqual()
expression to return for a Maybe
? Would it return true? Maybe! Would it return false? Maybe! We don't know - that's the entire point of the enum. That's why it makes sense to explicitly compare to No
, even though it's more verbose.
I don't usually use an explicit comparison with zero for integral or pointer types since the conversion-to-boolean is well-defined and obvious.
However, I always use an explicit comparison for enumerations, just in case someone changes the definition of the enumeration. You can never be sure that someone won't change the enumeration later, after all.
Relying on the underlying numeric value of an enumerator just seems like a bad idea.
This seems similar to Boost.Tribool. Tribool supports conversions to bool for use in conditional statements, which would seem to suggest that implicit conversion to bool in a case such as this is not bad, at least according to the Boost organization (whom I have found to be fairly reasonable).
What I don't like is that it is asymmetric.
E.g. what you really wanted somewhere was
if(typesEqual(t1, t2) == Yes) {
do_something();
}
but by accident you wrote
if(typesEqual(t1, t2)) {
do_something();
}
It seems somehow strange/ugly that you can use the boolean trick for No but not for Yes.
I think I would solve it by renaming the function to tryCompareTypes(t1, t2)
, and change your enum to
enum Result {
Maybe,
No,
Yes
};
So tryCompareTypes()
returns 0 if it "failed" to definitively decide whether the types are equal, otherwise it returns either No or Yes, both of which are nonzero and hence indicate "success".
精彩评论