Re: Compile time mapping

2019-05-12 Thread Bastiaan Veelo via Digitalmars-d-learn

On Sunday, 12 May 2019 at 18:47:20 UTC, Bogdan wrote:

On Sunday, 12 May 2019 at 17:53:56 UTC, Bastiaan Veelo wrote:
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?


My question was very vague, sorry about that.

In my use case I'd like to map SDL2 keyboard scan codes to my 
own game input keyboard codes. The two enums would look 
something like this:


```
enum SDL_Scancode
{
SDL_SCANCODE_UNKNOWN = 0,
SDL_SCANCODE_A = 4,
SDL_SCANCODE_B = 5,
SDL_SCANCODE_C = 6,
SDL_SCANCODE_D = 7,
}

enum MY_Scancode
{
  KEY_A,
  KEY_B,
  KEY_C,
  KEY_D,
}
```

The two enums are not of equal length, so in the end I just 
decided to create an immutable array of type My_Scancode[] 
where the index is an SDL_Scancode and the value is the 
corresponding MY_Scancode enum member. I'm ok with using some 
memory for this, as long as it's as fast as possible.


If the only difference is the extra _UNKNOWN member, you can 
still use the static foreach approach. Just make it a 
non-template function and rip out the checks, and add a +1 in the 
right place.


Re: Compile time mapping

2019-05-12 Thread Bogdan via Digitalmars-d-learn

On Sunday, 12 May 2019 at 17:53:56 UTC, Bastiaan Veelo wrote:
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?


My question was very vague, sorry about that.

In my use case I'd like to map SDL2 keyboard scan codes to my own 
game input keyboard codes. The two enums would look something 
like this:


```
enum SDL_Scancode
{
SDL_SCANCODE_UNKNOWN = 0,
SDL_SCANCODE_A = 4,
SDL_SCANCODE_B = 5,
SDL_SCANCODE_C = 6,
SDL_SCANCODE_D = 7,
}

enum MY_Scancode
{
  KEY_A,
  KEY_B,
  KEY_C,
  KEY_D,
}
```

The two enums are not of equal length, so in the end I just 
decided to create an immutable array of type My_Scancode[] where 
the index is an SDL_Scancode and the value is the corresponding 
MY_Scancode enum member. I'm ok with using some memory for this, 
as long as it's as fast as possible.


Re: Compile time mapping

2019-05-12 Thread Bastiaan Veelo via Digitalmars-d-learn

On Sunday, 12 May 2019 at 17:53:56 UTC, Bastiaan Veelo wrote:

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


There was an error in the error reporting. That should teach me 
to never copy+paste if you can static foreach :-) This one is 
better:


https://run.dlang.io/is/TVl9db


Re: Compile time mapping

2019-05-12 Thread Bastiaan Veelo via Digitalmars-d-learn

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


Re: Compile time mapping

2019-05-12 Thread Patrick Schluter via Digitalmars-d-learn

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?


An example of a Initial enum that creates a derived enum using 
the same element names but applying a transformation via a 
function foo() pus adding some other enum elements in the Derived 
one not present in the Initial.

It's a little bit clumsy but works very well.
I use this at module level. This allows to have the Derived enum 
at compile time so that it can be used to declare variables or 
functions at compile time.




mixin({
  string code = "enum Derived : ulong { "~
"init = 0,";  /* We set the dummy 
init value to 0 */

  static foreach(i; __traits(allMembers, Initial)) {
code ~= i~"= foo(Initial."~i~"),";
  }
  code ~= "
ALL=  Whatever,
THING  =  42,
  return code ~ "}";
}());




Re: Compile time mapping

2019-05-11 Thread Adam D. Ruppe via Digitalmars-d-learn

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?


I'd probably have either a definition of one in terms of the 
other:


enum Other {
   a = First.a,
   b = First.b
}

or a helper function that just converts:

Other convert(First v) {
   final switch(v) {
 case First.a: return Other.a;
 case First.b: return Other.b;
   }
}

and then call the function and it can ctfe it. The second one is 
probably more practical.


Compile time mapping

2019-05-11 Thread Bogdan via Digitalmars-d-learn
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?