www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to allocate an element of type T with value x in generic code?

reply "Tobias Pankrath" <tobias pankrath.net> writes:
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?
Apr 03 2013
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
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?
Apr 03 2013
parent reply "Tobias Pankrath" <tobias pankrath.net> writes:
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.
Apr 03 2013
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
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.
Apr 03 2013
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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.
Apr 03 2013
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
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.
Apr 03 2013
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Apr 03 2013
parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
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.
Apr 03 2013
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Apr 03 2013
parent "Tobias Pankrath" <tobias pankrath.net> writes:
Thank you for the answers, helped a lot!
Apr 03 2013
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
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
Apr 03 2013