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