Out of bound problem

Christopher Wright dhasenan at gmail.com
Sat Feb 16 18:58:08 PST 2008


bearophile wrote:
> While testing I have found a problem in my code, I have reduced the code to the following lines:
> 
> template IsArray(T) {
>     const bool IsArray = is(typeof(T.length)) && is(typeof(T.sort)) &&
>                          is(typeof(T.reverse)) && is(typeof(T.dup));
> }

...
Y'know, there's a template for this in std.traits and tango.core.Traits.

> TA[] foo(TA, TB)(TA[] a, TB b) {
>     TA[] result;
> 
>     static if (IsArray!(TB)) {
>         if (b.length == 0) {
>             result = a;
>         } else if (b.length == 1) {
>             result = foo(a, b[0]);
>         }
>     }
> 
>     return result;
> }
> 
> void main() {
>     foo("test", "");
> }
> 
> 
> Its output:
> 
> bug.d(13): Error: array index 0 is out of bounds b[0 .. 0]
> bug.d(13): Error: array index 0 is out of bounds b[0 .. 0]
> bug.d(13): Error: array index 0 is out of bounds b[0 .. 0]
> bug.d(21): template instance bug.foo!(char,char[0u]) error instantiating

Ouch! Constant expansion for the lose!

What's going on is, this is being evaluated at compile time, when you've 
got a runtime check for length. So it's expanded like this:

if ("".length == 0) {
    // blah
} else if ("".length == 1) {
    result = foo(blah, ""[0]);
}

Then the compiler sees: Array literal! Constant index! Must expand!
Obviously, it can't do that. So it gives an error.

So, you can use a static if, but that'll fail for a dynamic array. Or 
you can pass in ""[] rather than "". Or you can check if it's a static 
array, do a 'static if (array.length)' in that case, and in the case of 
a dynamic array, use a non-static if.

But yeah, it's a bug.

> I have found ways to solve this problem, but can someone please explain me what's the problem?
> 
> Bye and thank you,
> bearophile


More information about the Digitalmars-d-learn mailing list