www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Indexing an associative array with a list of types

reply Doctor J <nobody nowhere.com> writes:
I'd like to make a compile-time constant associative array mapping a list of
types to an integer:

int[??] typemap;

typemap[(int,float)] = 1;
typemap[(long,double)] = 2;
...
int t = typemap[(int,float)];

I tried playing with std.typetuple but no luck.  I can get halfway there with a
function template, but then I can't iterate over the keys or values.  Is there
a way to do something like this in D?  More generally, is there a way to store
a type in a variable?

Thanks.
Apr 11 2009
parent reply grauzone <none example.net> writes:
Doctor J wrote:
 I'd like to make a compile-time constant associative array mapping a list of
types to an integer:
 
 int[??] typemap;
 
 typemap[(int,float)] = 1;
 typemap[(long,double)] = 2;
 ...
 int t = typemap[(int,float)];
 
 I tried playing with std.typetuple but no luck.  I can get halfway there with
a function template, but then I can't iterate over the keys or values.  Is
there a way to do something like this in D?  More generally, is there a way to
store a type in a variable?
 
Just curious, how did you do this function template thing?
 Thanks.
 
Types are a compiletime only thing. To get a "runtime" handle for a type, use TypeInfo. For each type, there exists exactly one TypeInfo object instance. You can get this object with typeid(): TypeInfo ti = typeid(int); Your example above could actually be implemented like this: int[TypeInfo[]] typemap; typemap[[typeid(int), typeid(float)]] = 1; (Two [] bracket pairs because one is for indexing into the AA, and one is an array delegate for constructing the TypeInfo[] array, which is used as key.)
Apr 11 2009
next sibling parent Doctor J <nobody nowhere.com> writes:
grauzone Wrote:

 Just curious, how did you do this function template thing?
static int typesToInt(T1, T2) () { static if (is (T1 == int) && is (T2 == float)) return 1; else if (is (T1 == long) && is (T2 == double)) return 2; else static assert (false, "Unrecognized types."); } Yuck. :)
 Types are a compiletime only thing. To get a "runtime" handle for a 
 type, use TypeInfo. For each type, there exists exactly one TypeInfo 
 object instance. You can get this object with typeid():
 
 TypeInfo ti = typeid(int);
 
 Your example above could actually be implemented like this:
 
 int[TypeInfo[]] typemap;
 
 typemap[[typeid(int), typeid(float)]] = 1;
 
 (Two [] bracket pairs because one is for indexing into the AA, and one 
 is an array delegate for constructing the TypeInfo[] array, which is 
 used as key.)
Sweet! Exactly what I was looking for. Thanks. -John
Apr 11 2009
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
grauzone:
 int[TypeInfo[]] typemap;
This too may work, and avoids one indirection layer, but it leads to some troubles later:
 int[TypeInfo[2]] typemap;
Bye, bearophile
Apr 11 2009
prev sibling parent reply Doctor J <nobody nowhere.com> writes:
Hmm, not quite.

This works at runtime, but not at compile-time; I can't use classes at compile
time:

    http://www.digitalmars.com/d/2.0/function.html#interpretation

and TypeInfo is a class:

    http://www.digitalmars.com/d/2.0/phobos/object.html#TypeInfo

Basically, what I want to do is assign a unique integer ID to each combination
of type parameters of a template.  Aside from that, I'm having a heck of a time
just building an associative array at compile time.  From the link above, to
make CTFE work, it sounds like you basically can't reference any (non-constant)
state; is that the case?  So, for example, if I wanted to keep a list of all
compiled-in modules that (call a compile-time function to) register with the
mothership, I'm out of luck?
Apr 11 2009
parent reply grauzone <none example.net> writes:
What exactly are you trying to accomplish?

It seems that you want to use the AA in CTFE, but it doesn't work, 
because using AAs with classes as keys don't work in CTFE?
Apr 11 2009
parent reply Doctor J <nobody nowhere.com> writes:
grauzone Wrote:

 What exactly are you trying to accomplish?
 
 It seems that you want to use the AA in CTFE, but it doesn't work, 
 because using AAs with classes as keys don't work in CTFE?
Correct. At compile time, I want to build up an associative array mapping type tuples to integers. Then, again at compile time, I want to query it.
Apr 11 2009
next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Sat, Apr 11, 2009 at 10:11 PM, Doctor J <nobody nowhere.com> wrote:
 grauzone Wrote:

 What exactly are you trying to accomplish?

 It seems that you want to use the AA in CTFE, but it doesn't work,
 because using AAs with classes as keys don't work in CTFE?
Correct. =A0At compile time, I want to build up an associative array mapp=
ing type tuples to integers. =A0Then, again at compile time, I want to quer= y it. Ooh. Without some serious trickery, I don't know if that's possible. The thing is, nothing at compile time can have any kind of persistent state - in effect, everything you use or do at compile time must be pure. Having some kind of compile-time registry of types built up as they register themselves, while useful, can't really be done easily. I've seen some persistent state kept by awful, awful means (i.e. conditionally testing for the existence of and declaring uniquely-named symbols in order to store some kind of info) but there is no general mechanism for it.
Apr 11 2009
prev sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Doctor J wrote:
<snip>
 Correct.  At compile time, I want to build up an associative array
 mapping type tuples to integers.  Then, again at compile time, I want
 to query it.
How about this? ---------- import std.typetuple, std.stdio; template typesToInt(T1 : int, T2 : float) { const int typesToInt = 1; } template typesToInt(T1 : long, T2 : double) { const int typesToInt = 2; } template intToTypes(int T : 1) { alias TypeTuple!(int, float) intToTypes; } template intToTypes(int T : 2) { alias TypeTuple!(long, double) intToTypes; } // testing code from this point forward void listTypes(T...)() { writefln(); foreach (type; T) writefln(typeid(type)); } void main() { writefln(typesToInt!(int, float)); writefln(typesToInt!(long, double)); listTypes!(intToTypes!(1))(); listTypes!(intToTypes!(2))(); } ---------- HTH Stewart.
Apr 12 2009