February 05, 2013 Re: new T[size] vs .reserve - alloca | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Treleaven | On Tuesday, 5 February 2013 at 16:37:41 UTC, Nick Treleaven wrote:
> On 05/02/2013 16:17, Nick Treleaven wrote:
>> On 03/02/2013 13:22, bearophile wrote:
>>> Era Scarecrow:
>>>
>>>> On Sunday, 3 February 2013 at 09:11:59 UTC, Namespace wrote:
>>>>> Sure, but alloca has the same ugly interface as malloc. :/
>>>>
>>>> You mean that you have to specify how many raw bytes you want, then
>>>> cast it to what you need? I never thought alloca or malloc were that
>>>> ugly.
>>>
>>> The interface of alloca() is bug-prone. And it's not handy if you want
>>> to create a 2D or nD array on the stack :-) In bugzilla there is a
>>> preliminary request for better and less bug-prone VLAs for D.
>>
>> ^ I know you're aware of this, but maybe others might not know the
>> default-argument alloca wrapping trick:
>
> I've just realized this doesn't work for variable-length allocation:
>
> T[] stack(T)(size_t N, void* m = alloca(T.sizeof * N))
>
> Error: undefined identifier N, did you mean alias T?
>
> N is not visible in the caller's scope.
It does, just alias it.
//----
import std.stdio;
import core.stdc.stdlib:alloca;
T* stack(T)(void* m = alloca(T.sizeof))
{
return cast(T*)m;
}
T[] stack(T, alias N)(void* m = alloca(T.sizeof * N))
{
return (cast(T*)m)[0 .. N];
}
void main(string[] args)
{
int* p = stack!int();
int[] arr = stack!(int, 5)();
*p = 2;
arr[0] = 5;
writeln(*p);
writeln(arr);
}
//----
|
February 05, 2013 Re: new T[size] vs .reserve - alloca | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | Why not: [code] T[] stack(T, const size_t N)(void* m = alloca(T.sizeof * N)) { return (cast(T*)m)[0 .. N]; } [/code] ? |
February 05, 2013 Re: new T[size] vs .reserve - alloca | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On 05/02/2013 16:47, monarch_dodra wrote:
> On Tuesday, 5 February 2013 at 16:37:41 UTC, Nick Treleaven wrote:
>> I've just realized this doesn't work for variable-length allocation:
>>
>> T[] stack(T)(size_t N, void* m = alloca(T.sizeof * N))
>>
>> Error: undefined identifier N, did you mean alias T?
>>
>> N is not visible in the caller's scope.
>
> It does, just alias it.
>
> //----
> import std.stdio;
> import core.stdc.stdlib:alloca;
>
> T* stack(T)(void* m = alloca(T.sizeof))
> {
> return cast(T*)m;
> }
> T[] stack(T, alias N)(void* m = alloca(T.sizeof * N))
> {
> return (cast(T*)m)[0 .. N];
> }
This works if you know N at compile-time. But there doesn't seem to be a way to wrap alloca to accept a runtime-only value, e.g.:
// allocate as many ints as command-line parameters
int[] arr = stack!int(args.length);
|
February 05, 2013 Re: new T[size] vs .reserve - alloca | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Treleaven | On Tuesday, 5 February 2013 at 20:47:46 UTC, Nick Treleaven wrote:
> On 05/02/2013 16:47, monarch_dodra wrote:
>> On Tuesday, 5 February 2013 at 16:37:41 UTC, Nick Treleaven wrote:
>>> I've just realized this doesn't work for variable-length allocation:
>>>
>>> T[] stack(T)(size_t N, void* m = alloca(T.sizeof * N))
>>>
>>> Error: undefined identifier N, did you mean alias T?
>>>
>>> N is not visible in the caller's scope.
>>
>> It does, just alias it.
>>
>> //----
>> import std.stdio;
>> import core.stdc.stdlib:alloca;
>>
>> T* stack(T)(void* m = alloca(T.sizeof))
>> {
>> return cast(T*)m;
>> }
>> T[] stack(T, alias N)(void* m = alloca(T.sizeof * N))
>> {
>> return (cast(T*)m)[0 .. N];
>> }
>
> This works if you know N at compile-time. But there doesn't seem to be a way to wrap alloca to accept a runtime-only value, e.g.:
>
> // allocate as many ints as command-line parameters
> int[] arr = stack!int(args.length);
I don't have access to my compiler, but that *should*work. Did you try it? BTW, the syntax would be:
int[] arr = stack!(int, args.length)();
|
February 05, 2013 Re: new T[size] vs .reserve - alloca | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On 05/02/2013 21:02, monarch_dodra wrote:
> On Tuesday, 5 February 2013 at 20:47:46 UTC, Nick Treleaven wrote:
>> On 05/02/2013 16:47, monarch_dodra wrote:
>>> T[] stack(T, alias N)(void* m = alloca(T.sizeof * N))
>>> {
>>> return (cast(T*)m)[0 .. N];
>>> }
>>
>> This works if you know N at compile-time. But there doesn't seem to be
>> a way to wrap alloca to accept a runtime-only value, e.g.:
>>
>> // allocate as many ints as command-line parameters
>> int[] arr = stack!int(args.length);
>
> I don't have access to my compiler, but that *should*work. Did you try
> it? BTW, the syntax would be:
>
> int[] arr = stack!(int, args.length)();
I've just tried it with dmd 2.059 (haven't upgraded yet). I got:
Error: variable args cannot be read at compile time
void main(string[] args)
{
int[] arr = stack!(int, args.length)();
}
|
February 05, 2013 Re: new T[size] vs .reserve - alloca | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Treleaven | On 05/02/2013 21:13, Nick Treleaven wrote:
> I've just tried it with dmd 2.059 (haven't upgraded yet)
sorry, 2.060
|
February 05, 2013 Re: new T[size] vs .reserve - alloca | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Treleaven | On Tuesday, 5 February 2013 at 21:14:32 UTC, Nick Treleaven wrote:
> On 05/02/2013 21:13, Nick Treleaven wrote:
>> I've just tried it with dmd 2.059 (haven't upgraded yet)
>
> sorry, 2.060
Right, it's "alias" being finicky, because "args.length" isn't an actual variable (it's a property). The problem is not so much that it can't be "read" at compile time, that the compiler doesn't know what to alias to.
I'll file a bug report to try and see if we can't get a better message.
Use a named variable, or use a manifest constant:
//----
import std.stdio;
import core.stdc.stdlib:alloca;
T* stack(T)(void* m = alloca(T.sizeof))
{
return cast(T*)m;
}
T[] stack(T, alias N)(void* m = alloca(T.sizeof * N))
{
return (cast(T*)m)[0 .. N];
}
void main(string[] args)
{
auto n = args.length;
int[] arr = stack!(int, n)();
}
//----
|
February 06, 2013 Re: new T[size] vs .reserve - alloca | ||||
---|---|---|---|---|
| ||||
Posted in reply to monarch_dodra | On 05/02/2013 22:15, monarch_dodra wrote: > On Tuesday, 5 February 2013 at 21:14:32 UTC, Nick Treleaven wrote: >> On 05/02/2013 21:13, Nick Treleaven wrote: >>> I've just tried it with dmd 2.059 (haven't upgraded yet) >> >> sorry, 2.060 > > Right, it's "alias" being finicky, because "args.length" isn't an actual > variable (it's a property). The problem is not so much that it can't be > "read" at compile time, that the compiler doesn't know what to alias to. > > I'll file a bug report to try and see if we can't get a better message. OK, please post the link if/when you file it. > Use a named variable, or use a manifest constant: This works, thanks. > //---- > import std.stdio; > import core.stdc.stdlib:alloca; > > T* stack(T)(void* m = alloca(T.sizeof)) > { > return cast(T*)m; > } > T[] stack(T, alias N)(void* m = alloca(T.sizeof * N)) > { > return (cast(T*)m)[0 .. N]; > } > > void main(string[] args) > { > auto n = args.length; > int[] arr = stack!(int, n)(); > } > //---- |
February 06, 2013 Re: new T[size] vs .reserve - alloca | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 05/02/2013 16:39, bearophile wrote:
> Nick Treleaven:
>
>> ^ I know you're aware of this, but maybe others might not know the
>> default-argument alloca wrapping trick:
>
> For some usages it's an improvement over raw usage of alloca.
> I did see this in past, but sometimes I forget.
Sorry if I sounded critical, I didn't mean to ;-)
|
Copyright © 1999-2021 by the D Language Foundation