Stack-allocated arrays

Max Samukha samukha at voliacable.com.removethis
Wed Nov 12 10:23:49 PST 2008


On Thu, 13 Nov 2008 01:54:59 +0800, KennyTM~ <kennytm at gmail.com>
wrote:

>Janderson wrote:
>> KennyTM~ wrote:
>>> Janderson wrote:
>>>> Dave wrote:
>>>>>> I'd love for "scope foo = new T[len];" to do for arrays what "scope 
>>>>>> bar = new Class;" does for classes. And indeed, if it's too big the 
>>>>>> compiler
>>>>>
>>>>> I'm surprised it doesn't and see that as a bit inconsistent, with 
>>>>> the only serious argument against it being that 'scope' couldn't be 
>>>>> used for large dynamic arrays.
>>>>>
>>>>> But then again:
>>>>>
>>>>> class C
>>>>> {
>>>>>   int[264_000] a;
>>>>> }
>>>>>
>>>>> void foo()
>>>>> {
>>>>>    scope C c = new C;
>>>>>    ...
>>>>> }
>>>>>
>>>>> could also overflow the stack. In either case the work-around would 
>>>>> be the same (increase the stack size or not use 'scope').
>>>>>
>>>>
>>>> As a work around, I imagine it would be possible to write a template 
>>>> that used the above syntax with a static if that would change 
>>>> depending on the size:  Something like this (untested):
>>>>
>>>>
>>>> class FastArray(T, int size)
>>>>     if (size < 1000)
>>>> {
>>>>     T[size] a;
>>>>     ... Overload operators
>>>> }
>>>>
>>>> class FastArray(T, int size)
>>>>     if (size >= 1000)
>>>> {
>>>>     T a[] = new T[size];
>>>>     ... Overload operators
>>>> }
>>>>
>>>>
>>>> //Use
>>>>
>>>> void foo()
>>>> {
>>>>     scope FastArray array = new FastArray!(int, 10); //Stack
>>>>     scope FastArray array = new FastArray!(int, 10000); //Heap
>>>> }
>>>>
>>>> Of course you never know where you are in the stack, so nesting these 
>>>> to much would be bad.
>>>
>>> But this won't work if size is runtime-determined.
>> 
>> Thanks for clarifying my last point :)
>> 
>> -Joel
>
>Is it? I mean things like:
>
>   int size = read_from_stdin();
>   scope array = new FixedSizeArray!(int)(size);
>
>You can't do it FixedSizeArray!(int, size) because all template 
>arguments must be determined at compile time.
>
>The best solution I can think of, without compiler modification is a 
>struct/class that contains a static array member T[1024] and a dynamic 
>array member T[] initialized to null; and the code chooses which member 
>to use in the constructor. But this always occupies 1024*T.sizeof bytes 
>and there will always be a conditional (if) sticked to all access methods.
>
>I hope I don't misunderstand your last point :).

Mixin brute force:

import std.c.stdlib;

template FixedSizeArray(T, string name, alias size)
{
    mixin ("scope " ~ name ~ " = size > 1000 ? new T[size] :
(cast(T*)alloca(size * T.sizeof))[0..size];");
}

void main()
{
    size_t i = 100;

    mixin FixedSizeArray!(int, "arr", i);
    arr[] = 123;

    i = 10000;
    mixin FixedSizeArray!(int, "arr2", i);
    arr2[] = 123;
}



More information about the Digitalmars-d mailing list