bit-level logic operations on enums

Steven Schveighoffer schveiguy at yahoo.com
Fri Mar 1 15:00:57 PST 2013


On Fri, 01 Mar 2013 17:24:22 -0500, Era Scarecrow <rtcvb32 at yahoo.com>  
wrote:

> On Friday, 1 March 2013 at 21:27:25 UTC, Steven Schveighoffer wrote:
>> Then, when determining the type of an enum operation, if the two  
>> operands are of the same enum type (meaning, they haven't gone through  
>> any integer promotion), the result is the same enum type.
>>
>> So this unintuitively results in:
>>
>> enum A : int { a }
>> enum B : byte { b }
>>
>> A a;
>> B b;
>> writeln(typeof(a | a).stringof); // => A
>> writeln(typeof(b | b).stringof); // => int (byte is promoted to int)
>> writeln(typeof(a | b).stringof); // => int
>> writeln(typeof(a | 1).stringof); // => int
>> writeln(typeof(b | 1).stringof); // => int
>
>   The only way the first makes sense is the compiler knows that it's the  
> same value and is a no-op, thereby doesn't lose it's enum state; At  
> which case b|b should do the same thing. However I'm quite sure the  
> following is true, as otherwise it wouldn't make sense (Unless it knows  
> the enum can only ever be 0 and doesn't matter?)
>
>    writeln(typeof(a | A.a).stringof); // => int
>    writeln(typeof(A.a | a).stringof); // => int

I was sure too.  It's not.  Any operation between A types results in A.

writeln(typeof(a + a).stringof); // => A
writeln(typeof(a << a).stringof); // => A
writeln(typeof(a * a).stringof); // => A

>
>> I would push for one of 4 behaviors, which make some sense to me:
>>
>> 1. Math operations between two enum values of the same type ALWAYS  
>> result in the same enum type regardless of base type (like int-based  
>> enums)
>
>   Isn't this the same (or close enough) as 4?

It would make math between enums and integers type as integers, which  
would then not be assignable back to the enum. In fact, this is exactly  
how it works for ints.  Not so for smaller types.  I'm just going for  
consistency.

>
>> 2. Math operations between two enum values of the same type ALWAYS  
>> result in the base type (full-scale enforcement of "enum only contains  
>> values from the identified list")
>
>> 3. Operations between two enums or between an enum and an int, that  
>> result at compile-time in a valid member of the enum result in the enum  
>> type.  Otherwise, the operation is converted to the base type.
>
>   It might be okay to do it against compile-time known values as it can  
> then confirm if the value is even possible, but this seems inconsistent,  
> and can then break code if the enums values change.

I'm ok with breaking code if the result is a more consistent enum feature.

>> 4. Enums can be assigned any value from its base type, or any value  
>> implicitly convertible to that base type.
>
>   Then 'final switch' won't work, nor could you know if the value was  
> valid at any point and enums would be easy to abuse.

You can already do this.  See above.

-Steve


More information about the Digitalmars-d mailing list