Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
January 17, 2021 Template argument deduction not working with template specialization | ||||
---|---|---|---|---|
| ||||
While trying to use template specializations I noticed the argument deductions do not yield the same version as the ones yielded when being explicit. Example: > uint a = 1; > uint[] b = [2]; > TFoo(a); > TFoo!(uint[])(b); > void TFoo(T)(T a) { > pragma(msg, "T: " ~ T.stringof); > } > > void TFoo(T : T[])(T[] a) { > pragma(msg, "T[]: " ~ T.stringof); > } I noticed that an automatically deduced TFoo call always yields the first, while TFoo!(uint[]) yields the array version if present, and defaults to the first elsewise. Am I incorrect in expecting the same behavior when (ab)using argument deduction or does my usage make sense? I tried searching for this combination (deduction & specialization) but couldn't find another forum post / documentation example. |
January 17, 2021 Re: Template argument deduction not working with template specialization | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul | On 1/17/21 11:22 AM, Paul wrote:
> While trying to use template specializations I noticed the argument deductions do not yield the same version as the ones yielded when being explicit.
> Example:
>
>> uint a = 1;
>> uint[] b = [2];
>> TFoo(a);
>> TFoo!(uint[])(b);
>
>> void TFoo(T)(T a) {
>> pragma(msg, "T: " ~ T.stringof);
>> }
>>
>> void TFoo(T : T[])(T[] a) {
>> pragma(msg, "T[]: " ~ T.stringof);
>> }
>
> I noticed that an automatically deduced TFoo call always yields the first, while TFoo!(uint[]) yields the array version if present, and defaults to the first elsewise.
>
> Am I incorrect in expecting the same behavior when (ab)using argument deduction or does my usage make sense? I tried searching for this combination (deduction & specialization) but couldn't find another forum post / documentation example.
I've always hated that aspect of specialization. I don't really understand why it's valid (how can T be T[]?)
This works:
void TFoo(T : U[], U)(T a)
-Steve
|
January 17, 2021 Re: Template argument deduction not working with template specialization | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Sunday, 17 January 2021 at 16:42:27 UTC, Steven Schveighoffer wrote: > I've always hated that aspect of specialization. I don't really understand why it's valid (how can T be T[]?) I totally agree with that, that confuses me as well. > This works: > > void TFoo(T : U[], U)(T a) Oh cool, that's surprising to say the least. Thanks! This indeed works with argument deduction :) |
January 17, 2021 Re: Template argument deduction not working with template specialization | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul | On 1/17/21 3:41 PM, Paul wrote: > On Sunday, 17 January 2021 at 16:42:27 UTC, Steven Schveighoffer wrote: >> This works: >> >> void TFoo(T : U[], U)(T a) > > Oh cool, that's surprising to say the least. Thanks! This indeed works with argument deduction :) It's basically saying if T matches the pattern U[] for some U (which is actually defined now inside the function), then it's a match (and preferred over the non-specialized template). -Steve |
January 17, 2021 Re: Template argument deduction not working with template specialization | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul | I just figured out half of my frustration is caused by a collision between the 'alias this'd template possibillity and the normal one. For example: > struct Bar(uint size, V) { > V[size] blup; > alias blup this; > } > > void foo(S : T[], T)(S a) { > pragma(msg, "first"); > } > > void foo(S : Bar!(T, U), uint T, U)(S a) { > pragma(msg, "second"); > } > Bar!(2, int) bar; > foo(bar); Will cause "called with argument types `(Bar!(2u, int))` matches both:DUB" (And "undefined identifier `T`DUB", "undefined identifier `U`DUB", but thats a false positive :/) While removal of either will make it work fine, as would removal of the alias. Templating: > The template picked to instantiate is the one that is most specialized that fits the types of the TemplateArgumentList. Alias this: > If an aggregate declaration defines an opCmp or opEquals method, it will take precedence to that of the aliased this member. I was of the impression D only defaulted to the alias when the original implementation of a (member) function was missing / disfunctional. Shouldn't aliasing also follow this logic when using template specializations? (Even though it may not be a member function) |
Copyright © 1999-2021 by the D Language Foundation