Thread overview
overloading question
Sep 17, 2004
Ben Hinkle
Sep 17, 2004
Sean Kelly
Sep 17, 2004
Ben Hinkle
Sep 17, 2004
Andy Friesen
Sep 17, 2004
Sean Kelly
September 17, 2004
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
September 17, 2004
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
September 17, 2004
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

September 17, 2004
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
September 17, 2004
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