Thread overview
Detecting array type without template specialization?
May 09, 2006
Sean Kelly
May 12, 2006
Bruno Medeiros
May 09, 2006
Say I want a template to do different things if it's passed an array versus a non-array type.  I can do this easily with template specialization:

template Spoon(T)
{
    void knife()
    {
        writefln("single");
    }
}

template Spoon(T : T[])
{
    void knife()
    {
        writefln("array");
    }
}

...

mixin Spoon!(int) i;
mixin Spoon!(int[]) a;

i.knife();
a.knife();


That prints

single
array

As I'd like it to.

That works great, but what if I'm writing a much larger class, where most of the functionality would be the same between the array and non-array versions, and I only want to change, say, one function to work differently for arrays?  It would be redundant and cumbersome to have to copy most of the contents of one template to the other.

Something like this can be done for classes versus non-classes:

template Spoon(T)
{
    void knife()
    {
        static if(is(T : Object))
            writefln("class");
        else
            writefln("non-class");
    }
}

But is there any way to do this for array types?


May 09, 2006
Jarrett Billingsley wrote:
> Say I want a template to do different things if it's passed an array versus a non-array type.  I can do this easily with template specialization:
> 
> template Spoon(T)
> {
>     void knife()
>     {
>         writefln("single");
>     }
> }
> 
> template Spoon(T : T[])
> {
>     void knife()
>     {
>         writefln("array");
>     }
> }
> 
> ...
> 
> mixin Spoon!(int) i;
> mixin Spoon!(int[]) a;
> 
> i.knife();
> a.knife();
> 
> 
> That prints
> 
> single
> array
> 
> As I'd like it to.
> 
> That works great, but what if I'm writing a much larger class, where most of the functionality would be the same between the array and non-array versions, and I only want to change, say, one function to work differently for arrays?  It would be redundant and cumbersome to have to copy most of the contents of one template to the other.
> 
> Something like this can be done for classes versus non-classes:
> 
> template Spoon(T)
> {
>     void knife()
>     {
>         static if(is(T : Object))
>             writefln("class");
>         else
>             writefln("non-class");
>     }
> }
> 
> But is there any way to do this for array types? 

template isArrayType( T )       { const bool isArrayType = false; }
template isArrayType( T : T[] ) { const bool isArrayType = true;  }

template Spoon( T )
{
    void knife()
    {
        static if( isArrayType( T ) )
            writefln( "array" );
        else
            writefln( "not array" );
    }
}

This sort of thing is why I created std.traits in Ares.


Sean
May 10, 2006
"Sean Kelly" <sean@f4.ca> wrote in message news:e3qub9$odc$1@digitaldaemon.com...
> template isArrayType( T )       { const bool isArrayType = false; }
> template isArrayType( T : T[] ) { const bool isArrayType = true;  }
>
> template Spoon( T )
> {
>     void knife()
>     {
>         static if( isArrayType( T ) )
>             writefln( "array" );
>         else
>             writefln( "not array" );
>     }
> }

Oh cool.

Thanks :)


May 12, 2006
Sean Kelly wrote:
> Jarrett Billingsley wrote:
>> Say I want a template to do different things if it's passed an array versus a non-array type.  I can do this easily with template specialization:
>>
>> template Spoon(T)
>> {
>>     void knife()
>>     {
>>         writefln("single");
>>     }
>> }
>>
>> template Spoon(T : T[])
>> {
>>     void knife()
>>     {
>>         writefln("array");
>>     }
>> }
>>
>> ...
>>
>> mixin Spoon!(int) i;
>> mixin Spoon!(int[]) a;
>>
>> i.knife();
>> a.knife();
>>
>>
>> That prints
>>
>> single
>> array
>>
>> As I'd like it to.
>>
>> That works great, but what if I'm writing a much larger class, where most of the functionality would be the same between the array and non-array versions, and I only want to change, say, one function to work differently for arrays?  It would be redundant and cumbersome to have to copy most of the contents of one template to the other.
>>
>> Something like this can be done for classes versus non-classes:
>>
>> template Spoon(T)
>> {
>>     void knife()
>>     {
>>         static if(is(T : Object))
>>             writefln("class");
>>         else
>>             writefln("non-class");
>>     }
>> }
>>
>> But is there any way to do this for array types? 
> 
> template isArrayType( T )       { const bool isArrayType = false; }
> template isArrayType( T : T[] ) { const bool isArrayType = true;  }
> 
> template Spoon( T )
> {
>     void knife()
>     {
>         static if( isArrayType( T ) )
>             writefln( "array" );
>         else
>             writefln( "not array" );
>     }
> }
> 
> This sort of thing is why I created std.traits in Ares.
> 
> 
> Sean

It is kinda odd that the 'is expression' doesn't feature arrays as one of it's testable archetypes (it has: typedef struct union class interface enum function delegate)

-- 
Bruno Medeiros - CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D