Thread overview
Enumerating structs?
Jan 03, 2012
Heywood Floyd
Jan 03, 2012
Simen Kjærås
Jan 04, 2012
Heywood Floyd
January 03, 2012
Hello!


I have some structs

  struct A { int a; }
  struct B { int b, c; }

and I'd like to be able to enumerate them (preferrably as integers) based on their names. I've no idea how this would look, but
some pseudo code that would use this feature:

  // pseudo
  int type = stream.read!int();
  switch(type){
    case A.enumof:
      auto data = stream.read!A();
      // ...
    break;
    case B.enumof:
      // ...
    break;
    // ...

The idea here is to enable stuff like static if's etc and to enforce the connection between the struct and the enumeration. Right now
I have a separate enums, like so:

  enum {A_ENUM = 1, B_ENUM = 2};
  // ...
    case A_ENUM:
       auto data = stream.read!A();
       // ...
    break;
  //...

But this means the idea that struct A has the enumeration "1" is only by convention. So when I, for instance, refactor struct A to "C",
all code still compiles. It would be cool if it didn't, somehow. With this small example it's of course not a problem, but for larger
more complex code perhaps.

A naive idea I had was to let each struct have an enum:

  struct A{
    enum TYPE_ENUM = 1;
    int a;
  }

That would be refactor-friendly and be a strong connection, but then there's no guarantee two structs don't have the same enum,
of course. Another idea was to maybe use mixin to somehow construct the enum declaration:

  mixin enumByType!(A,B);

That could generate code like:

  enum {A_ENUM = 1, ...}

and then couple it with a

   // ...
   case typeEnumFor!A():
       //...
   break;
   // ...

but now it's starting to maybe feel a bit overkill?
Is there an easier/correct/other way?

-

I usually end up feeling like this a lot with D, I just realized. It's like, yes, with mixins I can more or less do anything, but where
does one stop? You know what I mean? I like it though. Mixin-paralysis : )


/HF









January 03, 2012
On Tue, 03 Jan 2012 16:35:29 +0100, Heywood Floyd <soul8o8@gmail.com> wrote:

>
> Hello!
>
>
> I have some structs
>
>   struct A { int a; }
>   struct B { int b, c; }
>
> and I'd like to be able to enumerate them (preferrably as integers) based on their names. I've no idea how this would look, but
> some pseudo code that would use this feature:
>
>   // pseudo
>   int type = stream.read!int();
>   switch(type){
>     case A.enumof:
>       auto data = stream.read!A();
>       // ...
>     break;
>     case B.enumof:
>       // ...
>     break;
>     // ...
>
> The idea here is to enable stuff like static if's etc and to enforce the connection between the struct and the enumeration. Right now
> I have a separate enums, like so:
>
>   enum {A_ENUM = 1, B_ENUM = 2};
>   // ...
>     case A_ENUM:
>        auto data = stream.read!A();
>        // ...
>     break;
>   //...
>
> But this means the idea that struct A has the enumeration "1" is only by convention. So when I, for instance, refactor struct A to "C",
> all code still compiles. It would be cool if it didn't, somehow. With this small example it's of course not a problem, but for larger
> more complex code perhaps.
>
> A naive idea I had was to let each struct have an enum:
>
>   struct A{
>     enum TYPE_ENUM = 1;
>     int a;
>   }
>
> That would be refactor-friendly and be a strong connection, but then there's no guarantee two structs don't have the same enum,
> of course. Another idea was to maybe use mixin to somehow construct the enum declaration:
>
>   mixin enumByType!(A,B);
>
> That could generate code like:
>
>   enum {A_ENUM = 1, ...}
>
> and then couple it with a
>
>    // ...
>    case typeEnumFor!A():
>        //...
>    break;
>    // ...
>
> but now it's starting to maybe feel a bit overkill?
> Is there an easier/correct/other way?
>
> -
>
> I usually end up feeling like this a lot with D, I just realized. It's like, yes, with mixins I can more or less do anything, but where
> does one stop? You know what I mean? I like it though. Mixin-paralysis :)


Yeah, D feels like that to me too, sometimes. Anyways, for your question -
would using the struct name be good enough? They're easy to get hold of
and usable in switch statements.

If not, how about this:


import std.typetuple;

struct TypeEnum( T... ) {
    static pure nothrow @property
    int value( U )( ) {
        static assert ( staticIndexOf!( U, T ) != -1 );
        return staticIndexOf!( U, T );
    }
}

struct A {}
struct B {}

void main( ) {
    alias TypeEnum!(A, B) types;

    assert( types.value!A == 0 );
    assert( types.value!B == 1 );
}
January 04, 2012
> Yeah, D feels like that to me too, sometimes. Anyways, for your question - would using the struct name be good enough? They're easy to get hold of and usable in switch statements.
>
> If not, how about this:
>
>
> import std.typetuple;
>
> struct TypeEnum( T... ) {
>     static pure nothrow @property
>     int value( U )( ) {
>         static assert ( staticIndexOf!( U, T ) != -1 );
>         return staticIndexOf!( U, T );
>     }
> }
>
> struct A {}
> struct B {}
>
> void main( ) {
>     alias TypeEnum!(A, B) types;
>
>     assert( types.value!A == 0 );
>     assert( types.value!B == 1 );
> }

Ha, yes, that looks quite nice!
Thanks!

/HF