Jump to page: 1 2
Thread overview
How to allocate an element of type T with value x in generic code?
Apr 03, 2013
Tobias Pankrath
Apr 03, 2013
John Colvin
Apr 03, 2013
Tobias Pankrath
Apr 03, 2013
John Colvin
Apr 03, 2013
Andrej Mitrovic
Apr 03, 2013
John Colvin
Apr 03, 2013
Ali Çehreli
Apr 03, 2013
John Colvin
Apr 03, 2013
Ali Çehreli
Apr 03, 2013
Tobias Pankrath
April 03, 2013
basic idea.
---
T x;
T* px = new T(x);
---
int x
int* px = new int(x); // fails
---

I need to do this for structs and basic types. What's the standard way to do this?
April 03, 2013
On Wednesday, 3 April 2013 at 11:05:06 UTC, Tobias Pankrath wrote:
> basic idea.
> ---
> T x;
> T* px = new T(x);
> ---
> int x
> int* px = new int(x); // fails
> ---
>
> I need to do this for structs and basic types. What's the standard way to do this?

Do you need to use new? i.e. do you need the variable to be allocated on the heap?
Also, as you've written it, px is not a pointer to x which is a bit misleading. What is the result you actually want?
April 03, 2013
On Wednesday, 3 April 2013 at 14:47:22 UTC, John Colvin wrote:
> On Wednesday, 3 April 2013 at 11:05:06 UTC, Tobias Pankrath wrote:
>> basic idea.
>> ---
>> T x;
>> T* px = new T(x);
>> ---
>> int x
>> int* px = new int(x); // fails
>> ---
>>
>> I need to do this for structs and basic types. What's the standard way to do this?
>
> Do you need to use new? i.e. do you need the variable to be allocated on the heap?
> Also, as you've written it, px is not a pointer to x which is a bit misleading. What is the result you actually want?

I need a fresh T (let's call it t) allocated on the heap and a pointer (pt) to it and the value of t should be the value of x.

---
T x;
int* pt = new T;
*pt = x;
---

Maybe I'll just do this.

April 03, 2013
On Wednesday, 3 April 2013 at 15:25:22 UTC, Tobias Pankrath wrote:
> On Wednesday, 3 April 2013 at 14:47:22 UTC, John Colvin wrote:
>> On Wednesday, 3 April 2013 at 11:05:06 UTC, Tobias Pankrath wrote:
>>> basic idea.
>>> ---
>>> T x;
>>> T* px = new T(x);
>>> ---
>>> int x
>>> int* px = new int(x); // fails
>>> ---
>>>
>>> I need to do this for structs and basic types. What's the standard way to do this?
>>
>> Do you need to use new? i.e. do you need the variable to be allocated on the heap?
>> Also, as you've written it, px is not a pointer to x which is a bit misleading. What is the result you actually want?
>
> I need a fresh T (let's call it t) allocated on the heap and a pointer (pt) to it and the value of t should be the value of x.
>
> ---
> T x;
> int* pt = new T;
> *pt = x;
> ---
>
> Maybe I'll just do this.

int* pt = new T; //that will only compile if T is int. I assume you meant:
T* pt = new T;

Other than that, what you have done there should work.

To avoid any superfluous initialisation of fields:

import core.memory : malloc;
T x;

T* pt = cast(T*)malloc(T.sizeof);
*pt = x;

note: this is not C malloc, the memory is requested from and managed by the GC.
April 03, 2013
On 4/3/13, John Colvin <john.loughran.colvin@gmail.com> wrote:
> note: this is not C malloc, the memory is requested from and managed by the GC.

Shouldn't that call be GC.malloc? I don't see a module-scoped malloc function anywhere except the C one in core.stdc.stdlib.
April 03, 2013
On 04/03/2013 08:53 AM, John Colvin wrote:

> import core.memory : malloc;
> T x;
>
> T* pt = cast(T*)malloc(T.sizeof);
> *pt = x;
>
> note: this is not C malloc, the memory is requested from and managed by
> the GC.

That assignment will fail in general when the left-hand side has those undetermined bits. std.conv.emplace is a safer option but it must be used differently for classes.

import std.stdio;
import core.memory;
import std.conv;


T * makeNew(T)(T rhs)
{
    static if (is(T == class)) {
        static assert(false); // not implemented

    } else {
        T * p = cast(T*)GC.calloc(T.sizeof);
        emplace!T(p, rhs);
        return p;
    }
}

struct S
{
    int i;
}

void main()
{
    writeln(*makeNew(42));
    writeln(*makeNew(1.5));
    writeln(*makeNew(S(1)));
}

The program should consider __traits(classInstanceSize) for classes.

Ali

April 03, 2013
On Wed, 03 Apr 2013 07:05:05 -0400, Tobias Pankrath <tobias@pankrath.net> wrote:

> basic idea.
> ---
> T x;
> T* px = new T(x);
> ---
> int x
> int* px = new int(x); // fails
> ---
>
> I need to do this for structs and basic types. What's the standard way to do this?

A crude but easy way to do this:

int *px = [x].ptr;

Only caveat is that the allocated block may be slightly bigger than necessary.  If you are concerned about footprint, you may want to do it with GC.malloc calls directly.

-Steve
April 03, 2013
On Wednesday, 3 April 2013 at 16:13:02 UTC, Andrej Mitrovic wrote:
> On 4/3/13, John Colvin <john.loughran.colvin@gmail.com> wrote:
>> note: this is not C malloc, the memory is requested from and
>> managed by the GC.
>
> Shouldn't that call be GC.malloc? I don't see a module-scoped malloc
> function anywhere except the C one in core.stdc.stdlib.

yes, you are correct.
April 03, 2013
On Wednesday, 3 April 2013 at 16:39:18 UTC, Ali Çehreli wrote:

> That assignment will fail in general when the left-hand side has those undetermined bits.

Could you expand on this? I don't fully understand.
April 03, 2013
On 04/03/2013 10:19 AM, John Colvin wrote:
> On Wednesday, 3 April 2013 at 16:39:18 UTC, Ali Çehreli wrote:
>
>> That assignment will fail in general when the left-hand side has those
>> undetermined bits.
>
> Could you expand on this? I don't fully understand.

In short, there is no object on the left-hand side.

GC.malloc() does not initialize the memory that it allocates. Assignment involves destroying the lhs object. (It is two operations packaged together: copy the right-hand side and destroy the left-hand side.)

If the uninitialized bits in the newly-allocated memory were invalid for T, then the destruction will fail or do something wrong.

The following program is sure to fail because 'fileName' happens to be a bad string when opAssign() is entered:

// WARNING: Your system may become unresponsive if you execute this program
import std.stdio;
import core.memory;
import std.exception;
import std.array;

struct S
{
    string fileName;

    this(string fileName)
    {
        enforce(!fileName.empty);
    }

    ref S opAssign(S rhs)
    {
        writefln("Stop using file %s", fileName);

        this.fileName = rhs.fileName;
        writefln("Start using file %s", fileName);

        return this;
    }

    ~this()
    {
        writefln("Destroying S with %s", fileName);
    }
}

void main()
{
    auto x = S("abc");

    S* pt = cast(S*)GC.malloc(S.sizeof);
    *pt = x;
}

Ali

« First   ‹ Prev
1 2