Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
July 07, 2020 Template function specialization doesn't work | ||||
---|---|---|---|---|
| ||||
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? |
July 07, 2020 Re: Template function specialization doesn't work | ||||
---|---|---|---|---|
| ||||
Posted in reply to IGotD- | 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);
}
}
|
July 07, 2020 Re: Template function specialization doesn't work | ||||
---|---|---|---|---|
| ||||
Posted in reply to IGotD- | 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
|
July 07, 2020 Re: Template function specialization doesn't work | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | 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
|
July 07, 2020 Re: Template function specialization doesn't work | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | 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. |
July 07, 2020 Re: Template function specialization doesn't work | ||||
---|---|---|---|---|
| ||||
Posted in reply to IGotD- | 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. |
July 07, 2020 Re: Template function specialization doesn't work | ||||
---|---|---|---|---|
| ||||
Posted in reply to IGotD- | 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 |
July 07, 2020 Re: Template function specialization doesn't work | ||||
---|---|---|---|---|
| ||||
Posted in reply to IGotD- | 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
|
Copyright © 1999-2021 by the D Language Foundation