How to search for an enum by values and why enum items aren't unique

stunaep via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Jul 27 06:59:54 PDT 2016


On Wednesday, 20 July 2016 at 05:45:21 UTC, Jonathan M Davis 
wrote:
> On Wednesday, July 20, 2016 04:03:23 stunaep via 
> Digitalmars-d-learn wrote:
>> How can I search for an enum by its values? For example I have
>>
>> >struct TestTraits {
>> >
>> > int value1;
>> > string value2;
>> >
>> >}
>> >
>> >enum Test : TestTraits {
>> >
>> > TEST = TestTraits(1, "test1"),
>> > TESTING = TestTraits(5, "test5")
>> >
>> >}
>>
>> and I have the int 5 and need to find TESTING with it.
>>
>> In java I would create a SearchableEnum interface, make all 
>> searchable enums implement it and use this method to find them.
>>
>> >public static <T extends SearchableEnum> T find(T[] vals, int
>> >id) {
>> >
>> > for (T val : vals) {
>> >
>> >     if (id == val.getId()) {
>> >
>> >         return val;
>> >
>> >     }
>> >
>> > }
>> > return null;
>> >
>> >}
>>
>> But the way enums work in D doesn't seem to permit this.
>
> If you want the list of members in an enum, then use 
> std.traits.EnumMembers and you'll get a compile-time list of 
> them. It can be made into a runtime list by being put into an 
> array literal.
>
> For instance, if we take std.datetime.Month, we can look for 
> the enum with the value 10 in it like so.
>
> auto found = [EnumMembers!Month].find(10);
> assert(found = [Month.oct, Month.nov, Month.dec]);
>
> So, if you had your TestTraits struct as the type for an enum, 
> you could do something like
>
> auto found = [EnumMembers!TestTraits].find!(a => a.value1 == 
> 5)();
> if(found.empty)
> {
>     // there is no TestTraits which matches
> }
> else
> {
>     // found.front is the match
> }
>
>> And why on earth are different enum items with the same values 
>> equal to each other? Say I have an enum called DrawableShape
>
> Because they have the same value. The fact that they're enums 
> doesn't change how they're compared. That's determined by what 
> type they are. All you're really getting with an enum is a list 
> of named constants that are grouped together which implicitly 
> convert to their base type but which are not converted to 
> implicitly from their base type. The only stuff that's going to 
> treat an enum member differently from any other value of that 
> type is something that specifically operates on enums - e.g. by 
> taking the enum type explicitly, or because it has is(T == 
> enum) and does something different for enums (quite a few 
> traits do that in std.traits), or because it uses a final 
> switch. Most code is just going to treat them like any other 
> value of the enum's base type. They aren't magically treated as 
> unique in some way just because they're in an enum.
>
> - Jonathan M Davis

So how would I make a function that takes an enum and an id as a 
parameter and returns a member in the enum? I tried for quite 
some time to do this but it wont let me pass Test as a parameter 
unless I use templates. I finally came up with this but it wont 
let me return null when there's nothing found

>E findEnumMember(E)(int id) if (is(E == enum)) {
>	auto found = [EnumMembers!E].find!(a => a.id == id)();
>	if(!found.empty)
>		return found.front;
>	else
>		...What do I return? null gives error
>}


More information about the Digitalmars-d-learn mailing list