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
}