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
}

Reply via email to