www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Overloading Based on Constraints

reply "jmh530" <john.michael.hall gmail.com> writes:
I was looking at
http://dlang.org/concepts.html
where it discusses overloading templates based on constraints. I 
wanted to try to overload a template function with another 
version that does everything in place. So basically, one has a 
return and the other doesn't. However, when I run the code, it 
only calls the first function. The second one is ignored. I tried 
a number of adjustments, but the only thing that worked is to 
re-name the function something else, remove the U's, and just 
have it be a void function.


import std.stdio : writeln;
import std.traits;

T test(T)(T x)
	if (isNumeric!(T))
{
	writeln("calling test without void");
	T y = x;
	y += 1;
	return y;
}

U test(T, U)(ref T x)
	if (isNumeric!(T) && is(U == void))
{
	writeln("calling test with void");
	x += 2;
}

void main()
{
	int a = 1;
	int b = test(a);
	writeln(b);
	int c = b;
	test(c);
	writeln(c);
}
Jul 23 2015
parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 7/23/15 5:58 PM, jmh530 wrote:
 I was looking at
 http://dlang.org/concepts.html
 where it discusses overloading templates based on constraints. I wanted
 to try to overload a template function with another version that does
 everything in place. So basically, one has a return and the other
 doesn't. However, when I run the code, it only calls the first function.
 The second one is ignored. I tried a number of adjustments, but the only
 thing that worked is to re-name the function something else, remove the
 U's, and just have it be a void function.
Just so you know, *every* template is tried for every call. So the if statements are not dependent on each other. Something I've wanted for a long time is an if-else mechanism for template constraints. What ends up happening is you have to repeat your constraints on every overload, but negate the previous ones. In any case, to your code:
 import std.stdio : writeln;
 import std.traits;

 T test(T)(T x)
      if (isNumeric!(T))
 {
      writeln("calling test without void");
      T y = x;
      y += 1;
      return y;
 }

 U test(T, U)(ref T x)
      if (isNumeric!(T) && is(U == void))
this will NEVER be called via IFTI, because U cannot be determined from the parameters. Return type (or how you use the result) does not play into IFTI at all. This is likely why it's never used, because it fails to instantiate. And note that regular overloading does not work like this. You can't overload on return type. Overloading on ref works, but only makes it so you can dictate how to handle rvalues vs. lvalues differently. -Steve
Jul 23 2015