On Monday, March 07, 2011 07:22:47 Wilfried Kirschenmann wrote:
> Hi,
> 
> I'm a beginner in D; I have just begun the book from Andrei.
> 
> I would like to know how to statically declare an associative array whose
> key are enums.
> 
> example :
> #!../dmd2/linux/bin/rdmd
> 
> import std.stdio, std.string;
> 
> enum deviceType {cpu, gpu}
> auto execDeviceSuffix = [deviceType.cpu:".cpu", deviceType.gpu:".gpu"];
> 
> void main(){
>   foreach(deviceSuffix; execDeviceSuffix.values) writeln(deviceSuffix);
> }
> 
> 
> This won't compile and give the error:
> Error: non-constant expression
> [cast(deviceType)0:".cpu",cast(deviceType)1:".gpu"]
> 
> I have two questions :
> 1) Why are there casts in the error message ?
> Are the enums always substituted by with their base type ?

You can use an enum where it's base type is required without any kind of casts. 
You do have to cast going the other way though. I'm quite sure why the cast is 
shown, but I believe that the compiler just replaces the enum variable with its 
value everywhere that it's used, and when printing enum variables, you get 
their 
value, which in this case would be indistinguishable from 0 in the case of 
deviceType.cpu. So, what's _probably_ happening is that it's replacing the enum 
variable with its value as well as a cast to the enum type (just like you would 
have to do if you used 0 directly).

> 2) where is the non constant part in this expression ?
> Both the deviceType enum and the strings are constant.
> 
> Thank you for your help !

I believe that the problem is that it doesn't consider the associative array to 
be constant. Not everything with associative arrays works with CTFE (compile 
time function evaluation) yet. I believe that if you use an associative array 
in 
a function used at compile time but the associative array isn't assigned to a 
global variable or anything which would stick around beyond compile time, it 
works, but it doesn't work if you try and keep the associative array beyond 
compile time (as you're obviously trying to do here). Most things that involve 
memory allocation on the heap fail at compile time (arrays are about the only 
exception, I believe, and I think that even they fail at times). Eventually, it 
is hoped that CTFE will reach the point that anything in SafeD will be valid, 
but it's not there yet. For the moment, you tend to need to try and use CTFE 
the 
way you'd want to and then fall back to setting the values at runtime where you 
can't.

The way to get what you want to work in this case is to use a module 
constructor. So, you'd do something like this:

string[deviceType] execDeviceSuffix;

static this()
{
        execDeviceSuffix[deviceType.cpu] = "cpu";
        execDeviceSuffix[deviceType.gpu] = "gpu";
}

The module constructor will be run before main does, so execDeviceSuffix will 
be 
properly filled in by then.

- Jonathan M Davis

Reply via email to