www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template function specialization doesn't work

reply IGotD- <nise nise.com> writes:
I have two template functions

void overloadedFunction(T)(ref T val)
{
...
}
	
	
void overloadedFunction(T : T[])(ref T[] s)
{
...
}

Obviously the second should be used when the parameter is a slice 
of any type, and the first should be used in other cases. However 
this doesn't happen, the compiler always picks the first function 
regardless if the parameter is a slice or not.

So

ubyte[3] ar = [ 1, 2, 3 ];
ubyte[] arSlice = ar;

overloadedFunction(arSlice);

The first function will be used. Shouldn't the template argument 
(T : T[]) make the compiler pick the second one?
Jul 07 2020
next sibling parent IGotD- <nise nise.com> writes:
On Tuesday, 7 July 2020 at 19:53:30 UTC, IGotD- wrote:
...
I also forgot to mention that the overloadedFunction is used in a variadic template function. void processAll(T...)(ref T t) { foreach(ref v; t) { overloadedFunction(v); } }
Jul 07 2020
prev sibling next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/7/20 3:53 PM, IGotD- wrote:
 I have two template functions
 
 void overloadedFunction(T)(ref T val)
 {
 ....
 }
 
 
 void overloadedFunction(T : T[])(ref T[] s)
 {
 ....
 }
 
 Obviously the second should be used when the parameter is a slice of any 
 type, and the first should be used in other cases. However this doesn't 
 happen, the compiler always picks the first function regardless if the 
 parameter is a slice or not.
 
 So
 
 ubyte[3] ar = [ 1, 2, 3 ];
 ubyte[] arSlice = ar;
 
 overloadedFunction(arSlice);
 
 The first function will be used. Shouldn't the template argument (T : 
 T[]) make the compiler pick the second one?
 
That specialization is... odd. It's basically saying, is T an array of T. I know I've seen this before, so I think it's valid. But maybe not? Have you tried (T: U[], U)(ref T[] s) ? -Steve
Jul 07 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/7/20 4:04 PM, Steven Schveighoffer wrote:

 Have you tried (T: U[], U)(ref T[] s) ?
Ugh... (T: U[], U)(ref T s) -Steve
Jul 07 2020
parent reply IGotD- <nise nise.com> writes:
On Tuesday, 7 July 2020 at 20:05:37 UTC, Steven Schveighoffer 
wrote:
 On 7/7/20 4:04 PM, Steven Schveighoffer wrote:

 Have you tried (T: U[], U)(ref T[] s) ?
Ugh... (T: U[], U)(ref T s) -Steve
Thank you, that worked and now it picked the correct overloaded function. I don't understand why and it is a bit counter intuitive. Why two template arguments as I'm not even us using U? If you look at the article https://dlang.org/articles/templates-revisited.html#specialization Then it mentioned that (T : T*) would work. Intuitively, then you would think (T : T[]) would work.
Jul 07 2020
parent reply IGotD- <nise nise.com> writes:
On Tuesday, 7 July 2020 at 20:14:19 UTC, IGotD- wrote:
 Thank you, that worked and now it picked the correct overloaded 
 function. I don't understand why and it is a bit counter 
 intuitive. Why two template arguments as I'm not even us using 
 U?

 If you look at the article

 https://dlang.org/articles/templates-revisited.html#specialization

 Then it mentioned that (T : T*) would work. Intuitively, then 
 you would think (T : T[]) would work.
Here (T : T[]) is even the example with the correct double[] type as a correct example as well. https://dlang.org/spec/template.html#parameters_specialization I'm confused.
Jul 07 2020
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/7/20 4:21 PM, IGotD- wrote:
 On Tuesday, 7 July 2020 at 20:14:19 UTC, IGotD- wrote:
 Thank you, that worked and now it picked the correct overloaded 
 function. I don't understand why and it is a bit counter intuitive. 
 Why two template arguments as I'm not even us using U?

 If you look at the article

 https://dlang.org/articles/templates-revisited.html#specialization

 Then it mentioned that (T : T*) would work. Intuitively, then you 
 would think (T : T[]) would work.
Here (T : T[]) is even the example with the correct double[] type as a correct example as well. https://dlang.org/spec/template.html#parameters_specialization I'm confused.
That's not IFTI, that's template instantiation. I bet if you did: overloadedFunction!(ubyte[])(arSlice) it would pick the second one. there is some extra magic going on for IFTI, and I'm not sure how it figures out what to do. I would agree with you that if explicit templates use that rule, so should IFTI. But perhaps there's a good reason why it can't be done. So possibly: overloadedFunction(arSlice) => Pattern match `ref T[]` to `ubyte[]` => T is ubyte => Check ubyte for T : T[], no match. -Steve
Jul 07 2020
prev sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 7/7/20 12:53 PM, IGotD- wrote:

 ubyte[3] ar = [ 1, 2, 3 ];
 ubyte[] arSlice = ar;
 
 overloadedFunction(arSlice);
 
 The first function will be used. Shouldn't the template argument (T : 
 T[]) make the compiler pick the second one?
There is also template constraints which may be useful: import std.traits; void overloadedFunction(T)(ref T val) if (!isArray!T) { writeln("general"); } void overloadedFunction(T)(ref T s) if (isArray!T) { writeln("T[]"); } Ali
Jul 07 2020