www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Q about template function overloads

reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Given a templated array-like class that looks like:

class Array(T)
{ ... }


How can I write a two overloaded versions of func, one which takes T[] 
and one which takes Array!(T), and have both return an Array!(T)?

In this case the Dummy trick[1] doesn't seem to be of much use.
[1] http://d.puremagic.com/issues/show_bug.cgi?id=337
That only seems to work when the Dummy is a specific type, not a 
parameterized type.

Am I stuck with static if's in this case?

What I'd like to write:

---------
// clean simple obvious, but doesn't compile
Array!(T) func(T)(Array!(T) a)
{
     ...
}

Array!(T) func(T)(T[] a)
{
     ...
}
---------


What I think I have to write instead

----------
// Not as clear or correct, but compiles
template _ArrayTForT(T)
{
     static if( is( T S: S[]) ) {
         alias ndarray!(S)  _ArrayTForT;
     }
     else { // really should check here that T==Array!(S) for some S
         alias T _ArrayTForT;
     }
}

_ArrayTForT!(T) diag(T)(T v) {
     alias _ArrayTForT!(T) ArrayT;
     static if( is( T S: S[]) )
     {
         writefln("T is a D array");
         return new ArrayT;
     }
     else { // should be more specific check!
         writefln("T is (maybe) an Array");
         return new ArrayT;
     }
}

-------------


Also how do I write the equivalent of this:

     static if( is( T S: S[]) ) {
         alias Array!(S)  _ArrayTForT;
     }

For the case where T is a user-defined array type:
     /// doesn't work!
     static if( is( T S: Array!(S)) ) {
         alias Array!(S)  _ArrayTForT;
     }
It really shouldn't just be an "else" catch-all in the code above.  It 
should be checking for an instantiation of Array!().

--bb
Dec 17 2006
next sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Bill Baxter wrote:

 Also how do I write the equivalent of this:
 
     static if( is( T S: S[]) ) {
         alias Array!(S)  _ArrayTForT;
     }
 
 For the case where T is a user-defined array type:
     /// doesn't work!
     static if( is( T S: Array!(S)) ) {
         alias Array!(S)  _ArrayTForT;
     }
 It really shouldn't just be an "else" catch-all in the code above.  It 
 should be checking for an instantiation of Array!().

This second part of my question seems to be a result of bug 688[1]. That is, the check 'is(T S:Array!(S))' *does* work if Array is a struct, just not if it's a class. But I would still be interested in any suggestions for how to do the overloading in a more elegant way. [1] http://d.puremagic.com/issues/show_bug.cgi?id=688 --bb
Dec 17 2006
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Gah, sorry to continue this monologue, but apparently my belief that the 
dummy trick wouldn't work ALSO came from a manifestation of bug 688.

This *does* work:

FooStruct!(T) func(T)(FooStruct!(T) a) {
     writefln("Calling FooStruct version");
     return a;
}

FooStruct!(T) func(dumm=void,T)(T[] a) {
     FooStruct!(T) ret;
     writefln("Calling [] version");
     return ret;
}

I think I'm going to have to put my blas/lapack array math module on 
hold for a bit till this bug gets fixed.  The errors and workarounds are 
becoming a little too detrimental to productivity.

--bb

Bill Baxter wrote:
 Bill Baxter wrote:
 
 Also how do I write the equivalent of this:

     static if( is( T S: S[]) ) {
         alias Array!(S)  _ArrayTForT;
     }

 For the case where T is a user-defined array type:
     /// doesn't work!
     static if( is( T S: Array!(S)) ) {
         alias Array!(S)  _ArrayTForT;
     }
 It really shouldn't just be an "else" catch-all in the code above.  It 
 should be checking for an instantiation of Array!().

This second part of my question seems to be a result of bug 688[1]. That is, the check 'is(T S:Array!(S))' *does* work if Array is a struct, just not if it's a class. But I would still be interested in any suggestions for how to do the overloading in a more elegant way. [1] http://d.puremagic.com/issues/show_bug.cgi?id=688 --bb

Dec 17 2006
prev sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
Bill Baxter wrote:
 Given a templated array-like class that looks like:
 
 class Array(T)
 { ... }
 
 
 How can I write a two overloaded versions of func, one which takes T[] 
 and one which takes Array!(T), and have both return an Array!(T)?
 
 In this case the Dummy trick[1] doesn't seem to be of much use.
 [1] http://d.puremagic.com/issues/show_bug.cgi?id=337
 That only seems to work when the Dummy is a specific type, not a 
 parameterized type.
 
 Am I stuck with static if's in this case?
 
 What I'd like to write:
 
 ---------
 // clean simple obvious, but doesn't compile
 Array!(T) func(T)(Array!(T) a)
 {
     ...
 }
 
 Array!(T) func(T)(T[] a)
 {
     ...
 }
 ---------

Hopefully these bugs you mention get fixed. I'm not very big on templates, something like this is how I would do a workaround: class Array(T) { alias T* ptr; // tag that matches T[].ptr ... } Array!(T) func(A, T = typeof(*A.ptr) )(A array) { static if ( is(A == Array!(T)) ) { pragma(msg, "Array!(T)"); ... } else { pragma(msg, "T[]"); ... } } Don't know if it is acceptable to you, but it works.
Dec 18 2006