Thread overview
Q about template function overloads
Dec 18, 2006
Bill Baxter
Dec 18, 2006
Bill Baxter
Dec 18, 2006
Bill Baxter
Dec 18, 2006
Lutger
December 18, 2006
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
December 18, 2006
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
December 18, 2006
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
December 18, 2006
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.