Jump to page: 1 2
Thread overview
How do I iterate over enum members at runtime?
Apr 09, 2011
Andrej Mitrovic
Apr 09, 2011
Jesse Phillips
Apr 09, 2011
Andrej Mitrovic
Apr 09, 2011
Jonathan M Davis
Apr 09, 2011
Andrej Mitrovic
Apr 10, 2011
Jesse Phillips
Apr 09, 2011
Cliff Hudson
Apr 09, 2011
Andrej Mitrovic
Apr 10, 2011
Jesse Phillips
Apr 10, 2011
Andrej Mitrovic
Apr 11, 2011
Dan Olson
Apr 11, 2011
Andrej Mitrovic
April 09, 2011
E.g.:

enum Metrics : int
{
	SM_CXSCREEN = 0,
	SM_CYSCREEN,
	SM_CXVSCROLL,
	SM_CYHSCROLL,
	SM_CYCAPTION,
	SM_CXBORDER,
}

void foo(int m)
{
}

void main()
{
    foreach (m; Metrics)
    {
        foo(m);
    }
}

This won't work.

I know there's traits to get strings at compile time, e.g.: auto b = [ __traits(allMembers, Metrics) ];

but this doesn't help me try out those enum values at runtime. It could almost work if I could use a mixin() in a foreach loop, but that's lucid dreaming.

Another alternative might be to create an array out of the enum, but I don't know of any way of doing this.
April 09, 2011
On Sat, 09 Apr 2011 16:20:06 -0400, Andrej Mitrovic wrote:

> I know there's traits to get strings at compile time, e.g.: auto b = [ __traits(allMembers, Metrics) ];
> 
> but this doesn't help me try out those enum values at runtime. It could almost work if I could use a mixin() in a foreach loop, but that's lucid dreaming.
> 
> Another alternative might be to create an array out of the enum, but I don't know of any way of doing this.

You have everything you need, just put them all together:

enum Metrics : int
{
	SM_CXSCREEN = 0,
	SM_CYSCREEN,
	SM_CXVSCROLL,
	SM_CYHSCROLL,
	SM_CYCAPTION,
	SM_CXBORDER,
}

void foo(int m)
{
}

void main()
{
    foreach (m; __traits(allMembers, Metrics))
    {
        foo(mixin("Metrics." ~ m));
    }
}

April 09, 2011
What the.. I was sure mixin wouldn't work in a foreach loop.

Thanks, Jesse!
April 09, 2011
> What the.. I was sure mixin wouldn't work in a foreach loop.

Whyever not? mixins work in most places. I believe that the problem is that they have to be a whole expression or statement rather than just a piece of one, so sometimes you can't use a mixin for something small and have to put more of the code in a mixin, but string mixins do work in most places.

- Jonathan M Davis
April 09, 2011
On 4/10/11, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
>> What the.. I was sure mixin wouldn't work in a foreach loop.
>
> Whyever not? mixins work in most places. I believe that the problem is that they have to be a whole expression or statement rather than just a piece of one, so sometimes you can't use a mixin for something small and have to put more of the code in a mixin, but string mixins do work in most places.
>
> - Jonathan M Davis
>

Well in this case it works, but it's not always so easy. For example:

import std.conv;
enum Metrics : int
{
    val0,
    val1,
    val2
}

void foo(int m)
{
}

void main()
{
   foreach (index; 0..3)
   {
       foo(mixin("Metrics.val" ~ to!string(index)));
   }
}

So even though you might think "hey, it's obvious index in this case can never be anything other than 0, 1, or 2", you still won't be able to compile this. CTFE is a tricky thing.
April 09, 2011
You could probably make a template out of the ugly __traits invocation as well?

On Sat, Apr 9, 2011 at 3:37 PM, Andrej Mitrovic <andrej.mitrovich@gmail.com>wrote:

> On 4/10/11, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> >> What the.. I was sure mixin wouldn't work in a foreach loop.
> >
> > Whyever not? mixins work in most places. I believe that the problem is
> that
> > they have to be a whole expression or statement rather than just a piece
> of
> > one, so sometimes you can't use a mixin for something small and have to
> put
> > more of the code in a mixin, but string mixins do work in most places.
> >
> > - Jonathan M Davis
> >
>
> Well in this case it works, but it's not always so easy. For example:
>
> import std.conv;
> enum Metrics : int
> {
>    val0,
>    val1,
>    val2
> }
>
> void foo(int m)
> {
> }
>
> void main()
> {
>    foreach (index; 0..3)
>   {
>       foo(mixin("Metrics.val" ~ to!string(index)));
>   }
> }
>
> So even though you might think "hey, it's obvious index in this case can never be anything other than 0, 1, or 2", you still won't be able to compile this. CTFE is a tricky thing.
>


April 09, 2011
Well, the C code I was translating had something like this:
struct SysMetrics
{
    int iIndex;
    char* szLabel;
    char* szDesc;
}

And then it used an array of these structures. So for all existing enums that started with "SM_", those fields were populated with the enum value and a name and description. A 200 line header file was filled by hand. I really hope the author had some help from an editor for that, lol!.

I've managed to do the same in about a dozen lines of code, although I didn't fill the description field (I don't need it anyway): http://codepad.org/EJEuc6qA

It's a shame that an enum with a tag doesn't have a .length property. I've had to use __traits to build an array just to get the length.
April 10, 2011
Andrej Mitrovic Wrote:

> It's a shame that an enum with a tag doesn't have a .length property. I've had to use __traits to build an array just to get the length.

It has .max

http://www.digitalmars.com/d/2.0/enum.html
April 10, 2011
You must iterate a compile time only construct.  So yes it would be nice to be able to say: static foreach and have the compiler tell you, no I can't do that (and force it if it can).

Andrej Mitrovic Wrote:

> Well in this case it works, but it's not always so easy. For example:
> 
> import std.conv;
> enum Metrics : int
> {
>     val0,
>     val1,
>     val2
> }
> 
> void foo(int m)
> {
> }
> 
> void main()
> {
>    foreach (index; 0..3)
>    {
>        foo(mixin("Metrics.val" ~ to!string(index)));
>    }
> }
> 
> So even though you might think "hey, it's obvious index in this case can never be anything other than 0, 1, or 2", you still won't be able to compile this. CTFE is a tricky thing.

April 10, 2011
On 4/10/11, Jesse Phillips <jessekphillips+D@gmail.com> wrote:
> Andrej Mitrovic Wrote:
>
>> It's a shame that an enum with a tag doesn't have a .length property. I've had to use __traits to build an array just to get the length.
>
> It has .max
>
> http://www.digitalmars.com/d/2.0/enum.html
>

That doesn't show me the number of values an enum tag has, only its largest value.

void main()
{
    writeln(foo.max);   // 101, not 4
}
enum foo : int
{
    a,
    b,
    c = 100,
    d
}
« First   ‹ Prev
1 2