www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Redirect to different overloads at compile time?

reply "David Bregman" <drb sfu.ca> writes:
Suppose I have a C library which implements a function for 
several types. C doesn't have overloading, so their names will be 
distinct.

extern(C):
double foo_double(double);
float foo_float(float);

Now I want to build a D wrapper, and merge them into a single 
function with overloading:

T foo(T)

I could write out the two overloads manually:
double foo(double d) { return foo_double(d); }
float foo(float f) { return foo_float(f); }

but this isn't compile time, it will generate a stub function for 
each overload, meaning the wrapper will have performance overhead 
unless inlining can be guaranteed somehow.

Is it possible to do something like
alias foo = foo_double;
alias foo = foo_float;

or

template(T) foo {
   static if(T is double) {
     alias foo = foo_double;
   } else {
     // etc.
   }
}

These doesn't work of course.

I don't fully understand the template syntax yet, but I have a 
feeling this is possible with templates. Is it possible to do 
what I'm trying to do?
Jun 29 2014
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Sun, 29 Jun 2014 22:24:09 -0400, David Bregman <drb sfu.ca> wrote:

 Suppose I have a C library which implements a function for several  
 types. C doesn't have overloading, so their names will be distinct.

 extern(C):
 double foo_double(double);
 float foo_float(float);

 Now I want to build a D wrapper, and merge them into a single function  
 with overloading:

 T foo(T)

 I could write out the two overloads manually:
 double foo(double d) { return foo_double(d); }
 float foo(float f) { return foo_float(f); }

 but this isn't compile time, it will generate a stub function for each  
 overload, meaning the wrapper will have performance overhead unless  
 inlining can be guaranteed somehow.
This is the correct answer. It should be inlined, and inlining should work as long as -inline is passed to the compiler. I don't think there is another way.
 Is it possible to do something like
 alias foo = foo_double;
 alias foo = foo_float;
Right, you cannot overload aliases as far as I know. foo either refers to foo_double, or foo_float. You can't bring in those as overloads under the name foo.
 or

 template(T) foo {
    static if(T is double) {
      alias foo = foo_double;
    } else {
      // etc.
    }
 }

 These doesn't work of course.
This last one looks like it should work. But IFTI ONLY works if you don't do what you did :) Basically, IFTI cannot see through static if to determine how to instantiate. It needs to be a clear single function. For example, how would IFTI figure it out if you did this? template(T) foo { static if(T is double) { alias foo = foo_float; } else { // etc. } } It can't figure out what T is without looking at what the alias would be, but in order to look at the alias, it needs to decide T!
 I don't fully understand the template syntax yet, but I have a feeling  
 this is possible with templates. Is it possible to do what I'm trying to  
 do?
It seems like it should be possible, but I think we would need a new type of implicit determination for templates that was not a function template. -Steve
Jun 29 2014
prev sibling parent reply "Kenji Hara" <k.hara.pg gmail.com> writes:
On Monday, 30 June 2014 at 02:24:10 UTC, David Bregman wrote:
 Suppose I have a C library which implements a function for 
 several types. C doesn't have overloading, so their names will 
 be distinct.

 extern(C):
 double foo_double(double);
 float foo_float(float);

 Now I want to build a D wrapper, and merge them into a single 
 function with overloading:

 T foo(T)

 I could write out the two overloads manually:
 double foo(double d) { return foo_double(d); }
 float foo(float f) { return foo_float(f); }

 but this isn't compile time, it will generate a stub function 
 for each overload, meaning the wrapper will have performance 
 overhead unless inlining can be guaranteed somehow.

 Is it possible to do something like
 alias foo = foo_double;
 alias foo = foo_float;
In D, you can merge arbitrary overloads by using alias declaration. import std.stdio; extern(C) { double foo_double(double a) { writeln(typeof(a).stringof); return a; } float foo_float (float a) { writeln(typeof(a).stringof); return a; } } alias foo = foo_double; alias foo = foo_float; void main() { double d; float f; foo(d); // prints double foo(f); // prints float } Kenji Hara
Jun 29 2014
parent "David Bregman" <drb sfu.ca> writes:
On Monday, 30 June 2014 at 04:50:05 UTC, Kenji Hara wrote:
 In D, you can merge arbitrary overloads by using alias 
 declaration.
Oh wow, you are right. That's a nice feature! I guess I simplified too much for the sake of making the post, the functions I would actually like to merge are function pointers. I assumed it was the same but I was wrong, sorry. double function(double d) foo_double; float function(float f) foo_float; In this case, trying to use alias to merge them causes an error.
Jun 29 2014