using enums as key in associative array
Jonathan M Davis
jmdavisProg at gmx.com
Mon Mar 7 11:16:58 PST 2011
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
More information about the Digitalmars-d-learn
mailing list