template specialization

Steven Schveighoffer schveiguy at yahoo.com
Wed Jun 9 05:44:51 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 byte.

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

-Steve


More information about the Digitalmars-d-learn mailing list