www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template specialization using traits?

reply Shriramana Sharma <samjnaa_dont_spam_me gmail.com> writes:
Hello. I want to define a template specialization using traits:

import std.stdio, std.traits;
void func(T)(T t) { writeln(1); }
void func(T)(T t) if(isIntegral!T) { writeln(2); }
void main()
{
    func(1);
}

But I'm getting an error saying that the called function matches both. If it 
were a single type, I know I have to put the specialization as in:

void func(T: int)(T t) { writeln(2); }

and that works, but how to make it more generic than that?

-- 

Dec 21 2015
next sibling parent rumbu <rumbu rumbu.ro> writes:
On Monday, 21 December 2015 at 09:44:20 UTC, Shriramana Sharma 
wrote:
 Hello. I want to define a template specialization using traits:

 import std.stdio, std.traits;
 void func(T)(T t) { writeln(1); }
 void func(T)(T t) if(isIntegral!T) { writeln(2); }
 void main()
 {
     func(1);
 }

 But I'm getting an error saying that the called function 
 matches both. If it were a single type, I know I have to put 
 the specialization as in:

 void func(T: int)(T t) { writeln(2); }

 and that works, but how to make it more generic than that?
void func(T)(T t) if(!isIntegral!T) { writeln(1); } void func(T)(T t) if(isIntegral!T) { writeln(2); } :)
Dec 21 2015
prev sibling parent reply Jonathan M Davis via Digitalmars-d-learn writes:
On Monday, December 21, 2015 15:14:20 Shriramana Sharma via Digitalmars-d-learn
wrote:
 Hello. I want to define a template specialization using traits:

 import std.stdio, std.traits;
 void func(T)(T t) { writeln(1); }
 void func(T)(T t) if(isIntegral!T) { writeln(2); }
 void main()
 {
     func(1);
 }

 But I'm getting an error saying that the called function matches both. If it
 were a single type, I know I have to put the specialization as in:

 void func(T: int)(T t) { writeln(2); }

 and that works, but how to make it more generic than that?
In D, each template constraint must match exactly once. A template with no template constraint is the same as having a template constraint that's always true. So, you need to alter your template constraints so that for a given template argument, exactly one template constraint is true. There really isn't such a thing as a specialization when dealing with template constraints. Using : like in your second example is the only kind of template specialization that we have. For your example to work with template constraints, the most straightforward solution would be void func(T)(T t) if(!isIntegral!T) { writeln(1); } void func(T)(T t) if(isIntegral!T) { writeln(2); } - Jonathan M Davis
Dec 21 2015
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, 21 December 2015 at 11:07:16 UTC, Jonathan M Davis 
wrote:
 For your example to work with template constraints, the most 
 straightforward solution would be

 void func(T)(T t)
     if(!isIntegral!T)
 {
     writeln(1);
 }

 void func(T)(T t)
     if(isIntegral!T)
 {
     writeln(2);
 }
Alternatively, you can use static if, though you're only dealing with one template in that case. e.g. void func(T)(T t) { static if(isIntegral!T) writeln(2); else writeln(1); } - Jonathan M Davis
Dec 21 2015
next sibling parent tcak <1ltkrs+3wyh1ow7kzn1k sharklasers.com> writes:
On Monday, 21 December 2015 at 11:12:10 UTC, Jonathan M Davis 
wrote:
 On Monday, 21 December 2015 at 11:07:16 UTC, Jonathan M Davis 
 wrote:
 For your example to work with template constraints, the most 
 straightforward solution would be

 void func(T)(T t)
     if(!isIntegral!T)
 {
     writeln(1);
 }

 void func(T)(T t)
     if(isIntegral!T)
 {
     writeln(2);
 }
Alternatively, you can use static if, though you're only dealing with one template in that case. e.g. void func(T)(T t) { static if(isIntegral!T) writeln(2); else writeln(1); } - Jonathan M Davis
Another alternative is: template func(T){ static if( isIntegral!T ){ void func(T t){ writeln( 2 ); } } else{ void func(T t){ writeln( 1 ); } } }
Dec 21 2015
prev sibling parent reply Shriramana Sharma <samjnaa_dont_spam_me gmail.com> writes:
Thanks all for your replies. One question:

Jonathan M Davis wrote:
 Alternatively, you can use static if, though you're only dealing
 with one template in that case. e.g.
But if we wanted to deprecate one of the alternatives, then we necessary need to declare two templates with the same name and complementary constraints right? --
Dec 21 2015
parent Jonathan M Davis via Digitalmars-d-learn writes:
On Monday, December 21, 2015 19:54:53 Shriramana Sharma via Digitalmars-d-learn
wrote:
 Thanks all for your replies. One question:

 Jonathan M Davis wrote:
 Alternatively, you can use static if, though you're only dealing
 with one template in that case. e.g.
But if we wanted to deprecate one of the alternatives, then we necessary need to declare two templates with the same name and complementary constraints right?
Yes. Symbols get deprecated, not the internals of functions. So, you need a separate function declaration to be able to deprecate one of them - though tcak's example that separates the template from the function and uses a static if within the template to declare two separate functions would allow for the deprecation to be inside of the static if, since the static if is outside of the function. Personally, I'd just use template constraints though. - Jonathan M Davis
Dec 21 2015