Thread overview
Indexing an associative array with a list of types
Apr 11, 2009
Doctor J
Apr 11, 2009
grauzone
Apr 11, 2009
Doctor J
Apr 12, 2009
bearophile
Apr 12, 2009
Doctor J
Apr 12, 2009
grauzone
Apr 12, 2009
Doctor J
Apr 12, 2009
Stewart Gordon
April 11, 2009
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.





April 11, 2009
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.)
April 11, 2009
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


April 12, 2009
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
April 12, 2009
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?


April 12, 2009
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?
April 12, 2009
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.


April 12, 2009
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.  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.

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.
April 12, 2009
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.