template specialization

Steven Schveighoffer schveiguy at yahoo.com
Wed Jun 9 05:51:20 PDT 2010


On Tue, 08 Jun 2010 17:25:43 -0400, Larry Luther <larry.luther at dolby.com>  
wrote:

> This code:
>
> import std.stdio;
>
>
> class A {
>
>   void get (T:ubyte)(T[] buffer) {
>     writefln( "get (T:ubyte)(T[] buffer)\n");
>   }
>
>   void get (T:byte)(T[] buffer) {
>     writefln( "get (T:byte)(T[] buffer)\n");
>   }
>
>   void get (T)(T[] buffer) {
>     writefln( "get (T)(T[] buffer)\n");
>   }
> }
>
>
> void main () {
>   A foo = new A;
>   ubyte[100] ub;
>   byte[100] bb;
>   int[100] ib;
>
>   foo.get( ub);
>   foo.get( bb);
>   foo.get( ib);
> }
>
> Generates:
>
>   get (T:ubyte)(T[] buffer)
>
>   get (T:ubyte)(T[] buffer)
>
>   get (T)(T[] buffer)
>
> Note:  If "get(T:byte)" preceeded "get(T:ubyte)" then "get(T:byte)"  
> would be
> called in both cases.
>
> Q: Is this the way it's supposed to be?
>
>   Thanks, Larry


Here is your mistake:

T:U as defined by the spec means any T that implicitly casts to U, not a T  
that exactly equals U.  Since ubyte and byte implicitly cast to eachother,  
the first template matches, no matter the order.

But there is a more subtle mistake in what you are doing.

The mistake is here:

> void get (T:ubyte)(T[] buffer) {
>   writefln( "get (T:ubyte)(T[] buffer)\n");
> }

You are assuming that because of this printout, the same instantiation is  
used.  BUT... The instantiations are different!

You should try this instead:

> void get (T:ubyte)(T[] buffer) {
>   writefln( "get (T:ubyte)(T[] buffer), T == %s\n", T.stringof);
> }

What you will find is the first template is used, but the template  
parameter T is correctly byte or ubyte depending on the call.

To do what you really want, use template constraints as Robert has  
suggested.  Before template constraints, the only way to do this properly  
is to use a static if.

I should also mention that a planned enhancement for the compiler is to  
make it so this kind of junk isn't necessary, you should just be able to  
do this:

>   void get (ubyte[] buffer) {
>   }
>
>   void get (byte[] buffer) {
>   }
>
>   void get (T)(T[] buffer) {
>   }

I know this is planned, because it's in TDPL.  BTW, are there any bug  
reports for this?

-Steve


More information about the Digitalmars-d-learn mailing list