digitalmars.D.learn - template specialization
- Larry Luther (30/30) Jun 08 2010 This code:
- Simen kjaeraas (4/8) Jun 08 2010 Looks very much correct, yes. Is there a problem?
- Robert Clipsham (9/10) Jun 08 2010 Yes, byte implicitly casts to ubyte so it's accepted. Try switching the
- Ellery Newcomer (10/20) Jun 08 2010 bit odd though, since byte[] isn't implicitly convertible to ubyte[].
- Larry Luther (6/6) Jun 08 2010 Thanks guys.
- Don (3/10) Jun 08 2010 No, C++ does it that way, and it gets horrendously complicated.
- Steven Schveighoffer (22/65) Jun 09 2010 Here is your mistake:
- bearophile (4/6) Jun 09 2010 Please write one, overloading of functions with templates is an importan...
- Trass3r (1/3) Jun 09 2010 http://d.puremagic.com/issues/show_bug.cgi?id=3941
- Larry Luther (1/1) Jun 10 2010 Thanks everyone.
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
Jun 08 2010
Larry Luther <larry.luther dolby.com> wrote:get (T:ubyte)(T[] buffer) get (T:ubyte)(T[] buffer) get (T)(T[] buffer) Q: Is this the way it's supposed to be?Looks very much correct, yes. Is there a problem? -- Simen
Jun 08 2010
On 08/06/10 22:25, Larry Luther wrote:Q: Is this the way it's supposed to be?Yes, byte implicitly casts to ubyte so it's accepted. Try switching the templates round, they will both be byte. The way around this is to add template constraints to the templates: void get(T:ubyte)(T[] buffer) if( is( T == ubyte ) ) { } void get(T:byte)(T[] buffer) if( is( T == byte ) ) { } etc. Hope this helps, Robert
Jun 08 2010
On 06/08/2010 05:01 PM, Robert Clipsham wrote:On 08/06/10 22:25, Larry Luther wrote:bit odd though, since byte[] isn't implicitly convertible to ubyte[]. no wait! yes it is! void get(T:ubyte[])(T t){} .. get(new byte[](1)); no wait! no it isn't! ubyte[] u = new byte[](1); and is it just me, or does the following silently cast away immutability? get("hi mom!");Q: Is this the way it's supposed to be?Yes, byte implicitly casts to ubyte so it's accepted. Try switching the templates round, they will both be byte. The way around this is to add template constraints to the templates: void get(T:ubyte)(T[] buffer) if( is( T == ubyte ) ) { } void get(T:byte)(T[] buffer) if( is( T == byte ) ) { } etc. Hope this helps, Robert
Jun 08 2010
Thanks guys. Simen asked: "Is there a problem?". Well, I kind of expected a "ubyte" buffer to be matched with a "get(T:ubyte)". I thought methods were searched for the "best" match. Larry
Jun 08 2010
Larry Luther wrote:Thanks guys. Simen asked: "Is there a problem?". Well, I kind of expected a "ubyte" buffer to be matched with a "get(T:ubyte)". I thought methods were searched for the "best" match.No, C++ does it that way, and it gets horrendously complicated. In D, it has to match exactly.
Jun 08 2010
On Tue, 08 Jun 2010 17:25:43 -0400, Larry Luther <larry.luther 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, LarryHere 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
Jun 09 2010
Steven Schveighoffer:I know this is planned, because it's in TDPL. BTW, are there any bug reports for this?Please write one, overloading of functions with templates is an important and basic thing. Bye, bearophile
Jun 09 2010
Please write one, overloading of functions with templates is an important and basic thing.http://d.puremagic.com/issues/show_bug.cgi?id=3941
Jun 09 2010