static if check for array and AA

Sean Kelly sean at f4.ca
Thu Jun 22 07:04:23 PDT 2006


Kirk McDonald wrote:
> Sean Kelly wrote:
>> Kirk McDonald wrote:
>>
>>>
>>> I'd forgotten about those .keys and .values properties. :-)
>>
>>
>> For extra credit, come up with a simple way to detect static arrays 
>> that doesn't rely on implementation-defined behavior. :-)
>>
>>
>> Sean
> 
> My first stab at this is this non-working template:
> 
> template isStaticArray(T) {
>     const bool isStaticArray = is(typeof(T.init[0])[T.length] == T);
> }
> 
> My reasoning being a bit of the spec that claims "length" is a 
> compile-time constant for static arrays. Makes sense, might even be 
> true... but it turns out something else entirely is wrong:
> 
> [inittest.d]
> import std.stdio;
> 
> void main() {
>     int[] a;
>     int[10] b;
>     writefln("%s\n%s",
>         typeof(a).init,
>         typeof(b).init
>     );
>     static if(is(typeof(typeof(b).init) == int)) {
>         writefln("(int[10]).init is an int!");
>     }
> }
> 
> $ dmd inittest
> $ ./inittest
> []
> 0
> (int[10]).init is an int!
> 
> Wait, what?
> 
> It turns out the above template fails because "is(typeof(T.init[0]))" 
> fails, as it doesn't describe a valid type. (You can't subscript an int!)
> 
> This oddity actually makes our job easier, as we see below.
> 
> It also seems that T.length isn't a compile time constant after all (or 
> at least the template doesn't work if I use it), but there's an easy 
> workaround: Divide T's sizeof by T.init's sizeof. The working template, 
> then, is:
> 
> template isStaticArray(T) {
>     const bool isStaticArray =
>         is(typeof(T.init)[(T).sizeof / typeof(T.init).sizeof] == T);
> }
> 
> Ugly! But it works.

Thanks :-)  I was trying to sort something like this out the other day 
and couldn't come up with a working syntax... but then I'd completely 
forgotten about tricks with .init.  At the time, I was thinking it might 
be nice if this detected static arrays:

template isStaticArray( T : T[int] ) {
     const bool isStaticArray = true;
}

template isStaticArray( T ) {
     const bool isStaticArray = false;
}

But since the type identifier would still be different from dynamic 
arrays, specializing templates for all arrays (dynamic and static) is 
still annoying:

template fn( T, bool isArray : true = isStaticOrDynamicArray!(T) ) {
     void fn( T ar ) {}
}

Then more mess to determine the element type of the array, etc.

I'm starting to wonder if C++ style template specialization is even the 
correct way to go about things in D, as it seems far more flexible to 
use a single generic wrapper containing a big static if block.  This 
seems to be the rough equivalent to concepts in D, with the drawback 
that at that point the template will either be instantiated or it won't 
and compilation will halt.


Sean



More information about the Digitalmars-d mailing list