www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template argument deduction not working with template specialization

reply Paul <paultjeadriaanse gmail.com> writes:
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.
Jan 17 2021
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
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
Jan 17 2021
parent reply Paul <paultjeadriaanse gmail.com> writes:
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 :)
Jan 17 2021
parent Steven Schveighoffer <schveiguy gmail.com> writes:
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
Jan 17 2021
prev sibling parent Paul <paultjeadriaanse gmail.com> writes:
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)
Jan 17 2021