www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template specialization

reply Darrell Gallion <dgallion1 gmail.com> writes:
How do you create a template that accepts many types.
But overrides just one of them?
Don't want to write out all of the specializations.

Hours of google and I'm sure it's simple...

-=Darrell
Jan 21
next sibling parent "H. S. Teoh via Digitalmars-d-learn" <digitalmars-d-learn puremagic.com> writes:
On Thu, Jan 21, 2016 at 11:37:34PM +0000, Darrell Gallion via
Digitalmars-d-learn wrote:
 How do you create a template that accepts many types.
 But overrides just one of them?
 Don't want to write out all of the specializations.
 
 Hours of google and I'm sure it's simple...
[...] I'm afraid your question is a little too ambiguous. Could you rephrase what it is you're trying to accomplish? Maybe with some code snippet that you want to work but currently doesn't? I'm not sure I understand why you have to write out any of the specializations at all... or what you mean by "override". T -- It always amuses me that Windows has a Safe Mode during bootup. Does that mean that Windows is normally unsafe?
Jan 21
prev sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 01/21/2016 03:37 PM, Darrell Gallion wrote:
 How do you create a template that accepts many types.
 But overrides just one of them?
 Don't want to write out all of the specializations.

 Hours of google and I'm sure it's simple...

 -=Darrell
The straightforward approach is tricky because the ': int' syntax means "is implicitly convertible"; so, even the case where B is 'char' would be bound to the specialization: void foo(A, B, C)() { pragma(msg, "general"); } void foo(A, B : int, C)() { // <-- 'B : int' specialization pragma(msg, "special"); } void main() { foo!(char, string, double)(); foo!(short, int, float)(); } A better approach is using template constraints: void foo(A, B, C)() if (!is (B == int)) { // <-- 'B != int' pragma(msg, "general"); } void foo(A, B, C)() if (is (B == int)) { // <-- 'B == int' pragma(msg, "special"); } void main() { foo!(char, string, double)(); foo!(short, int, float)(); } But that has its own problem of needing to reverse the logic for the general case (and other cases), which may become very complicated to write (or to get right) in some cases. Ali
Jan 21
parent reply Darrell Gallion <dgallion1 gmail.com> writes:
On Friday, 22 January 2016 at 00:08:56 UTC, Ali Çehreli wrote:
 On 01/21/2016 03:37 PM, Darrell Gallion wrote:
 How do you create a template that accepts many types.
 But overrides just one of them?
 Don't want to write out all of the specializations.

 Hours of google and I'm sure it's simple...

 -=Darrell
The straightforward approach is tricky because the ': int' syntax means "is implicitly convertible"; so, even the case where B is 'char' would be bound to the specialization: void foo(A, B, C)() { pragma(msg, "general"); } void foo(A, B : int, C)() { // <-- 'B : int' specialization pragma(msg, "special"); } void main() { foo!(char, string, double)(); foo!(short, int, float)(); } A better approach is using template constraints: void foo(A, B, C)() if (!is (B == int)) { // <-- 'B != int' pragma(msg, "general"); } void foo(A, B, C)() if (is (B == int)) { // <-- 'B == int' pragma(msg, "special"); } void main() { foo!(char, string, double)(); foo!(short, int, float)(); } But that has its own problem of needing to reverse the logic for the general case (and other cases), which may become very complicated to write (or to get right) in some cases. Ali
I must apologize for such a vague question. Frustration had me. import std.stdio; void foo(A)() if (!is (A == int)) { pragma(msg, "int"); } void foo(A)() if (is (A == int[])) { pragma(msg, "int[]"); } void main() { foo!(int)(); foo!(int[])(); } =========== source\app.d(15): Error: template app.foo cannot deduce function from argument types !(int)(), candidates are: source\app.d(3): app.foo(A)() if (!is(A == int)) source\app.d(8): app.foo(A)() if (is(A == int[])) source\app.d(16): Error: app.foo called with argument types () matches both: source\app.d(3): app.foo!(int[]).foo() and: source\app.d(8): app.foo!(int[]).foo()
Jan 21
parent reply Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Friday, 22 January 2016 at 01:33:42 UTC, Darrell Gallion wrote:
 void foo(A)()
         if (!is (A == int)) {
     pragma(msg, "int");
 }

 void foo(A)()
         if (is (A == int[])) {
     pragma(msg, "int[]");
 }

 void main() {

   foo!(int)();
   foo!(int[])();
 }

 ===========

 source\app.d(15): Error: template app.foo cannot deduce 
 function from argument types !(int)(), candidates are:
 source\app.d(3):        app.foo(A)() if (!is(A == int))
 source\app.d(8):        app.foo(A)() if (is(A == int[]))
 source\app.d(16): Error: app.foo called with argument types () 
 matches both:
 source\app.d(3):     app.foo!(int[]).foo()
 and:
 source\app.d(8):     app.foo!(int[]).foo()
Have a look at the first template constraint. It checks whether the template parameter _is not_ `int`, so of course, the first instantiation fails, and the second one is ambiguous.
Jan 22
parent reply Darrell Gallion <dgallion1 gmail.com> writes:
On Friday, 22 January 2016 at 11:23:56 UTC, Marc Schütz wrote:
 On Friday, 22 January 2016 at 01:33:42 UTC, Darrell Gallion 
 wrote:
 void foo(A)()
         if (!is (A == int)) {
     pragma(msg, "int");
 }

 void foo(A)()
         if (is (A == int[])) {
     pragma(msg, "int[]");
 }

 void main() {

   foo!(int)();
   foo!(int[])();
 }

 ===========

 source\app.d(15): Error: template app.foo cannot deduce 
 function from argument types !(int)(), candidates are:
 source\app.d(3):        app.foo(A)() if (!is(A == int))
 source\app.d(8):        app.foo(A)() if (is(A == int[]))
 source\app.d(16): Error: app.foo called with argument types () 
 matches both:
 source\app.d(3):     app.foo!(int[]).foo()
 and:
 source\app.d(8):     app.foo!(int[]).foo()
Have a look at the first template constraint. It checks whether the template parameter _is not_ `int`, so of course, the first instantiation fails, and the second one is ambiguous.
I'm aware this doesn't look right or compile. How do I do this? void foo(int x) { } void foo(int [] x) { } template foo(T)(T x){} void main() { int x; int [] a; foo((x); foo(a); foo("hi"); }
Jan 22
next sibling parent reply Darrell Gallion <dgallion1 gmail.com> writes:
On Friday, 22 January 2016 at 13:03:52 UTC, Darrell Gallion wrote:
 On Friday, 22 January 2016 at 11:23:56 UTC, Marc Schütz wrote:
 On Friday, 22 January 2016 at 01:33:42 UTC, Darrell Gallion 
 wrote:
 void foo(A)()
         if (!is (A == int)) {
     pragma(msg, "int");
 }

 void foo(A)()
         if (is (A == int[])) {
     pragma(msg, "int[]");
 }

 void main() {

   foo!(int)();
   foo!(int[])();
 }

 ===========

 source\app.d(15): Error: template app.foo cannot deduce 
 function from argument types !(int)(), candidates are:
 source\app.d(3):        app.foo(A)() if (!is(A == int))
 source\app.d(8):        app.foo(A)() if (is(A == int[]))
 source\app.d(16): Error: app.foo called with argument types 
 () matches both:
 source\app.d(3):     app.foo!(int[]).foo()
 and:
 source\app.d(8):     app.foo!(int[]).foo()
Have a look at the first template constraint. It checks whether the template parameter _is not_ `int`, so of course, the first instantiation fails, and the second one is ambiguous.
I'm aware this doesn't look right or compile. How do I do this? void foo(int x) { } void foo(int [] x) { } template foo(T)(T x){} void main() { int x; int [] a; foo((x); foo(a); foo("hi"); }
What was getting me... Defining the templates within another function, fails. void main(){ long foo(T: int)(T t) { return cast(long)t; } long[] foo(T: int[])(T t) { long [] ar; return ar; } T foo(T)(T t) { return t; } foo(1); foo([1,2]); foo("hi"); } source/app.d(224,3): Error: declaration foo(T : int[])(T t) is already defined source/app.d(229,3): Error: declaration foo(T)(T t) is already defined source/app.d(236,6): Error: template D main.foo cannot deduce function from argument types !()(int[]), candidates are: source/app.d(219,8): app.main.foo(T : int)(T t) source/app.d(237,6): Error: template D main.foo cannot deduce function from argument types !()(string), candidates are: source/app.d(219,8): app.main.foo(T : int)(T t)
Jan 22
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 01/22/2016 07:41 AM, Darrell Gallion wrote:

 Defining the template [specializations] within another function, fails.
Reported: https://issues.dlang.org/show_bug.cgi?id=15592 Ali
Jan 22
prev sibling parent Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Friday, 22 January 2016 at 13:03:52 UTC, Darrell Gallion wrote:
 On Friday, 22 January 2016 at 11:23:56 UTC, Marc Schütz wrote:
 On Friday, 22 January 2016 at 01:33:42 UTC, Darrell Gallion 
 wrote:
 void foo(A)()
         if (!is (A == int)) {
     pragma(msg, "int");
 }

 void foo(A)()
         if (is (A == int[])) {
     pragma(msg, "int[]");
 }

 void main() {

   foo!(int)();
   foo!(int[])();
 }

 ===========

 source\app.d(15): Error: template app.foo cannot deduce 
 function from argument types !(int)(), candidates are:
 source\app.d(3):        app.foo(A)() if (!is(A == int))
 source\app.d(8):        app.foo(A)() if (is(A == int[]))
 source\app.d(16): Error: app.foo called with argument types 
 () matches both:
 source\app.d(3):     app.foo!(int[]).foo()
 and:
 source\app.d(8):     app.foo!(int[]).foo()
Have a look at the first template constraint. It checks whether the template parameter _is not_ `int`, so of course, the first instantiation fails, and the second one is ambiguous.
I'm aware this doesn't look right or compile. How do I do this?
Just remove the `!` in the first template constraint, and it will compile.
 void foo(int x)
 { }

 void foo(int [] x)
 { }

 template foo(T)(T x){}

 void main() {
   int x;
   int [] a;
   foo((x);
   foo(a);
   foo("hi");
 }
You lost me here...
Jan 22