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