Thread overview
something cool: templated typedefs
Jul 22, 2004
Sean Kelly
Jul 22, 2004
Sha Chancellor
Jul 22, 2004
Sean Kelly
July 22, 2004
It just occurred to me this morning to see if I could get templated typedefs to work in D.  This is at the top of my wish list for C++ and I was excited to see that they already work in D.  Here's an example:

# class Map(T,U)
# {
#     T key;
#     U val;
# }
#
# template IntMap(U)
# {
#     alias Map!(int,U) IntMap;
# }
#
# int main()
# {
#     Map!(char, char) cmap = new Map!(char, char)();
#     IntMap!(char) imap = new IntMap!(char)();
#
#     printf( "%.*s\t%.*s\n%.*s\t%.*s\n",
#             typeid( typeof( cmap.key ) ).toString(),
#             typeid( typeof( cmap.val ) ).toString(),
#             typeid( typeof( imap.key ) ).toString(),
#             typeid( typeof( imap.val ) ).toString() );
#    return 0;
# }

prints:

char    char
int     char

I'm really starting to like the way D handles templates.  This auto-collapsing of template names is starting to look *very* useful.


Sean


July 22, 2004
In message <cdovkl$v8f$1@digitaldaemon.com>
 Sean Kelly <sean@f4.ca> wrote:

>that they already work in D.  Here's an example:
>
># class Map(T,U)
># {
>#     T key;
>#     U val;
># }
>#
># template IntMap(U)
># {
>#     alias Map!(int,U) IntMap;
># }
>#
># int main()
># {
>#     Map!(char, char) cmap = new Map!(char, char)();
>#     IntMap!(char) imap = new IntMap!(char)();
>#
>#     printf( "%.*s\t%.*s\n%.*s\t%.*s\n",
>#             typeid( typeof( cmap.key ) ).toString(),
>#             typeid( typeof( cmap.val ) ).toString(),
>#             typeid( typeof( imap.key ) ).toString(),
>#             typeid( typeof( imap.val ) ).toString() );
>#    return 0;
># }
>
>prints:
>
>char    char
>int     char
>
>I'm really starting to like the way D handles templates.  This auto-collapsing of template names is starting to look *very* useful.


Why is it you can do imap.key and imap.val.  Shouldn't this need to be
done like:
IntMap!(char).IntMap imap = new IntMap!(char).IntMap.

Or is there some special thing going on when there's an alias to
something with the same name as a template?  I thought templates had their own
namespace..  What's going on here seems very mystical to me.
Right from the template specification:

TemplateInstance:
        template TFoo(T) { alias T* t; }
        ...
        TFoo!(int).t x; // declare x to be of type int*

A template instantiation can be aliased:
        template TFoo(T) { alias T* t; }
        alias TFoo!(int) abc;
        abc.t x;        // declare x to be of type int*

July 22, 2004
In article <cdp9pi$13ns$1@digitaldaemon.com>, Sha Chancellor says...
>
>In message <cdovkl$v8f$1@digitaldaemon.com>
> Sean Kelly <sean@f4.ca> wrote:
>
>>that they already work in D.  Here's an example:
>>
>># class Map(T,U)
>># {
>>#     T key;
>>#     U val;
>># }
>>#
>># template IntMap(U)
>># {
>>#     alias Map!(int,U) IntMap;
>># }
>>#
>># int main()
>># {
>>#     Map!(char, char) cmap = new Map!(char, char)();
>>#     IntMap!(char) imap = new IntMap!(char)();
>>#
>>#     printf( "%.*s\t%.*s\n%.*s\t%.*s\n",
>>#             typeid( typeof( cmap.key ) ).toString(),
>>#             typeid( typeof( cmap.val ) ).toString(),
>>#             typeid( typeof( imap.key ) ).toString(),
>>#             typeid( typeof( imap.val ) ).toString() );
>>#    return 0;
>># }
>>
>>prints:
>>
>>char    char
>>int     char
>>
>>I'm really starting to like the way D handles templates.  This auto-collapsing of template names is starting to look *very* useful.
>
>Why is it you can do imap.key and imap.val.  Shouldn't this need to be
>done like:
>IntMap!(char).IntMap imap = new IntMap!(char).IntMap.
>
>Or is there some special thing going on when there's an alias to
>something with the same name as a template?  I thought templates had their own
>namespace..  What's going on here seems very mystical to me.

The key is the section on implicit template properties.  The text reads: "if a template has exactly one member in it, and the name of that member is the same as the template name, that member is assumed to be referred to in a template instantiation."  ie.

# template foo(T)
# {
#     void foo( T t ) {}
# }

can be called as:

# foo!(int)( 5 );

ie. it's the same as doing:

# foo!(int).foo(5);

The important thing to note is that the standard mentions no restrictions on what the member has to be.  So my example:

# template IntMap(U)
# {
#     alias Map!(int,U) IntMap;
# }

would normally be called as:

# IntMap!(char).IntMap mymap;

but collapses to:

# IntMap!(char) mymap;


Sean