www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - overloading question

reply Ben Hinkle <bhinkle4 juno.com> writes:
I have a question about overloading and templates. Here's my problem. I have
a function that I want to overload with another function. The trouble is
the function is in a template. For example I have something like

template foo(T) {
  void foo(T* x) {...}
}
template foo(T) {
  void foo(T[] x) {...}
}

I want users to write code that looks like
 foo!(int)(y);
no matter if y is int* or int[]. The two templates as written above don't
work because one can't have two templates with the same name in the same
scope. So right now I'm using static opCalls:
struct foo(T) {
  static void opCall(T* x) {...}
  static void opCall(T[] x) {...}
}

I could write something like
template foo(T) {
  void foo(T* x) {...}
  void foo(T[] x) {...}
}
and make users write
 foo!(int).foo(y)
but I'd prefer not to do that. If I try writing
 foo!(int)(y)
the compiler complains
 function expected before (), not 'void'

Basically I'm arguing that the special case of allowing users to write 
 foo!(int)(...)
when foo has the form
template foo(T) {
  void foo(...)
}
should be extended to handle overloaded functions in the template. If there
is a way to do this currently that is less hacky than using static opCalls
please let me know.

-Ben
Sep 16 2004
parent reply Sean Kelly <sean f4.ca> writes:
Ben Hinkle wrote:
 I have a question about overloading and templates. Here's my problem. I have
 a function that I want to overload with another function. The trouble is
 the function is in a template. For example I have something like
 
 template foo(T) {
   void foo(T* x) {...}
 }
 template foo(T) {
   void foo(T[] x) {...}
 }
 
 I want users to write code that looks like
  foo!(int)(y);
 no matter if y is int* or int[]. The two templates as written above don't
 work because one can't have two templates with the same name in the same
 scope.

But you can have two specialized templates with the same name in the same scope: C:\code\d\demo>type overload.d template foo(T) { void foo(T x) { printf( "generic\n" ); } } template foo(T : T*) { void foo(T* x) { printf( "pointer\n" ); } } template foo(T : T[]) { void foo(T[] x) { printf( "array\n" ); } } void main() { int x = 5; int a[1]; foo!(int)(5); foo!(int*)(&x); foo!(int[])(a); } C:\code\d\demo>dmd overload.d C:\bin\dmd\bin\..\..\dm\bin\link.exe overload,,,user32+kernel32/noi; C:\code\d\demo>overload generic pointer array
Sep 16 2004
parent reply Ben Hinkle <bhinkle4 juno.com> writes:
Sean Kelly wrote:

 Ben Hinkle wrote:
 I have a question about overloading and templates. Here's my problem. I
 have a function that I want to overload with another function. The
 trouble is the function is in a template. For example I have something
 like
 
 template foo(T) {
   void foo(T* x) {...}
 }
 template foo(T) {
   void foo(T[] x) {...}
 }
 
 I want users to write code that looks like
  foo!(int)(y);
 no matter if y is int* or int[]. The two templates as written above don't
 work because one can't have two templates with the same name in the same
 scope.

But you can have two specialized templates with the same name in the same scope: C:\code\d\demo>type overload.d template foo(T) { void foo(T x) { printf( "generic\n" ); } } template foo(T : T*) { void foo(T* x) { printf( "pointer\n" ); } } template foo(T : T[]) { void foo(T[] x) { printf( "array\n" ); } } void main() { int x = 5; int a[1]; foo!(int)(5); foo!(int*)(&x); foo!(int[])(a); } C:\code\d\demo>dmd overload.d C:\bin\dmd\bin\..\..\dm\bin\link.exe overload,,,user32+kernel32/noi; C:\code\d\demo>overload generic pointer array

cool - thanks! I hadn't thought of using specialization. I'll still have a problem when I want to specialize on associative arrays but I didn't get into that in my original post. I actually want my templates to take 2 parameters (Key,Value) and specialize for various containers. My I'll try foo(Key,Value:Value[Key]) or something... thanks again though
Sep 17 2004
parent reply Andy Friesen <andy ikagames.com> writes:
Ben Hinkle wrote:
 
 cool - thanks! I hadn't thought of using specialization.
 
 I'll still have a problem when I want to specialize on associative arrays
 but I didn't get into that in my original post. I actually want my
 templates to take 2 parameters (Key,Value) and specialize for various
 containers. My I'll try foo(Key,Value:Value[Key]) or something...
 
 thanks again though
 

If you figure this one out, I'd love to know. I tried to work this out awhile ago, but never got anywhere. It's possible to specialize on an associative array if the key or value type is not a template argument, or if the key and value types are identical, but, as far as I can tell, that's the limit of what D's template specialization mechanism is capable of: template Foo(T : int[T]) // works template Foo(T : T[int]) // works template Foo(T : T[T]) // works template Foo(T,U : T[U]) // useless: requires Foo!(int, int[char[]]) -- andy
Sep 17 2004
parent Sean Kelly <sean f4.ca> writes:
In article <cieohm$1av6$1 digitaldaemon.com>, Andy Friesen says...
If you figure this one out, I'd love to know.  I tried to work this out 
awhile ago, but never got anywhere.

It's possible to specialize on an associative array if the key or value 
type is not a template argument, or if the key and value types are 
identical, but, as far as I can tell, that's the limit of what D's 
template specialization mechanism is capable of:

     template Foo(T,U : T[U]) // useless: requires Foo!(int, int[char[]])

I'm pretty sure this is a bug. Perhaps it should go in the MIID thread. Sean
Sep 17 2004