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");
}
```