On Saturday, 11 May 2019 at 15:48:44 UTC, Bogdan wrote:
What would be the most straight-forward way of mapping the members of an enum to the members of another enum (one-to-one mapping) at compile time?

If I understand your question correctly, you have two enums of equal length, and you want to convert members across enums according to their position, right? You can do that with a little bit of template programming and static foreach. The following works irrespective of underlying value and type, the only requirement is that there are no duplicate values:

https://run.dlang.io/is/dNssel
```
void main()
{
    enum FromEnum {F1 = 10, F2, F3}
    enum ToEnum   {T1 = 20, T2, T3}
    enum CharEnum : char {C1 = 'c', C2, C3}

    static assert(to!ToEnum(FromEnum.F2) == ToEnum.T2);
    static assert(to!ToEnum(FromEnum.F2) == 21);
    static assert(to!CharEnum(FromEnum.F2) == CharEnum.C2);
    static assert(to!CharEnum(FromEnum.F2) == 'd');
}

// Converts enumerations by position.
T to(T, F)(F f) if (is(F==enum) && is(T == enum))
{
    import std.traits;
    import std.meta;
static assert(NoDuplicates!(EnumMembers!F).length == EnumMembers!F.length,
                  F.stringof ~ " has duplicates.");
static assert(NoDuplicates!(EnumMembers!T).length == EnumMembers!T.length,
                  F.stringof ~ " has duplicates.");
    static assert(EnumMembers!F.length == EnumMembers!T.length,
F.stringof ~ " and " ~ T.stringof ~ " differ in length.");
    static foreach(i, t; EnumMembers!T)
        if (rank(f) == i)
            return t;
    assert(0, "Not an enum member");
}

// Returns i if e is the i-th enumerator of E.
static size_t rank(E)(E e) if (is(E == enum))
{
    import std.traits;
    static foreach (i, member; EnumMembers!E)
        if (e == member)
            return i;
    assert(0, "Not an enum member");
}
```

Reply via email to