Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
December 15, 2016 Allocating a class within another class during object init w/o passing in an allocator | ||||
---|---|---|---|---|
| ||||
Hello, It is my understanding that a class can have a struct as one of its members, and it will be allocated in-line with the rest of the class' members. My question is this; how might I be able to do this with another class? I want to be able to allocate Foo using std.experimental.allocator without having to pass in a reference to the actual allocator. Thanks. eg: class SomeClass {} class Foo { this(IAllocator alloc) { sc = alloc.make!SomeClass; this.alloc = alloc } ~this() { alloc.dispose(sc); } size_t something; SomeClass sc; IAllocator alloc } auto foo = alloc.make!Foo(alloc); vs. struct SomeStruct {} class Foo { this() { ss = SomeStruct (...); } size_t something; SomeStruct ss; } auto foo = alloc.make!Foo; |
December 15, 2016 Re: Allocating a class within another class during object init w/o passing in an allocator | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Zhang | On Thursday, 15 December 2016 at 17:44:23 UTC, David Zhang wrote:
>
would something like this be a solution ?
import std.stdio;
import std.experimental.allocator;
class SomeClass {
int someint = 42;
static SomeClass opCall(int a) {
auto inst = theAllocator.make!SomeClass;
inst.someint += a;
return inst;
}
void destruct() {
theAllocator.dispose(this);
}
}
class Foo {
this() {
sc = SomeClass(7);
sc.someint -= 42;
}
~this() {
sc.destruct();
}
size_t something;
SomeClass sc;
}
void main(string[] args) {
auto foo = theAllocator.make!Foo;
assert(foo.sc.someint == 7);
theAllocator.dispose(foo);
}
|
December 15, 2016 Re: Allocating a class within another class during object init w/o passing in an allocator | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Zhang | On 12/15/2016 06:44 PM, David Zhang wrote: > It is my understanding that a class can have a struct as one of its > members, and it will be allocated in-line with the rest of the class' > members. Yup. > My question is this; how might I be able to do this with > another class? I want to be able to allocate Foo using > std.experimental.allocator without having to pass in a reference to the > actual allocator. Add a fixed-size array with an appropiate size to the class, and use std.conv.emplace to construct the object there: ---- class SomeClass {} class Foo { this() { import std.conv: emplace; sc = emplace!SomeClass(scStorage); } SomeClass sc; void[__traits(classInstanceSize, SomeClass)] scStorage; } void main() { import std.experimental.allocator: make; import std.experimental.allocator.mallocator: Mallocator; auto foo = Mallocator.instance.make!Foo; } ---- I haven't considered alignment here. I'm not sure if you have to. The GC will collect the sc object along with the parent Foo. Be cautious of that when you allow public access to sc. You can also replace the sc field with a method that creates the class reference on the fly (it's just a cast): ---- class Foo { this() { import std.conv: emplace; emplace!SomeClass(scStorage); } @property SomeClass sc() { return cast(SomeClass) scStorage.ptr; } void[__traits(classInstanceSize, SomeClass)] scStorage; } ---- |
December 15, 2016 Re: Allocating a class within another class during object init w/o passing in an allocator | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | Thank you for your responses. Visitor, I don't want any reference to an allocator within the class if I can avoid it. ag0aep6g, thanks! That's what I was looking for. However, it leaves me with another question, how much (if any) space would the static array require from the class? It's not a strict necessity for me, but I'm curious. |
December 15, 2016 Re: Allocating a class within another class during object init w/o passing in an allocator | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Zhang | On 12/15/2016 09:51 PM, David Zhang wrote:
> However, it leaves me with another question, how
> much (if any) space would the static array require from the class?
Depends on SomeClass. The array's size is just the value of __traits(classInstanceSize, SomeClass). There's no overhead.
You can print such stuff at compile time with pragma(msg, ...):
----
pragma(msg, __traits(classInstanceSize, SomeClass));
pragma(msg, Foo.scStorage.sizeof); /* same */
----
|
December 15, 2016 Re: Allocating a class within another class during object init w/o passing in an allocator | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | On Thursday, 15 December 2016 at 21:08:51 UTC, ag0aep6g wrote:
> On 12/15/2016 09:51 PM, David Zhang wrote:
>> However, it leaves me with another question, how
>> much (if any) space would the static array require from the class?
>
> Depends on SomeClass. The array's size is just the value of __traits(classInstanceSize, SomeClass). There's no overhead.
>
> You can print such stuff at compile time with pragma(msg, ...):
>
> ----
> pragma(msg, __traits(classInstanceSize, SomeClass));
> pragma(msg, Foo.scStorage.sizeof); /* same */
> ----
So the size of Foo would be the size of SomeClass plus members? ie. Is the size of the array stored too?
|
December 15, 2016 Re: Allocating a class within another class during object init w/o passing in an allocator | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Zhang | On Thursday, 15 December 2016 at 21:37:34 UTC, David Zhang wrote: > So the size of Foo would be the size of SomeClass plus members? ie. Is the size of the array stored too? With these definitions: ---- class SomeClass {} class Foo { this() { import std.conv: emplace; emplace!SomeClass(scStorage); } @property SomeClass sc() { return cast(SomeClass) scStorage.ptr; } void[__traits(classInstanceSize, SomeClass)] scStorage; } ---- the "instance size" of Foo is the size of a) Foo's hidden/implicit fields which all classes have, plus b) the size of scStorage which is Foo's only explicit field. The size of scStorage is the instance size of SomeClass (just the implicit fields here). The size/length of scStorage is known at compile-time. It's not stored in Foo. |
December 16, 2016 Re: Allocating a class within another class during object init w/o passing in an allocator | ||||
---|---|---|---|---|
| ||||
Posted in reply to ag0aep6g | > I haven't considered alignment here. I'm not sure if you have to. I though all classes were aligned to sizeof(size_t) boundaries? Wouldn't it then just be align(sizeof(size_t)) byte[__traits(classInstanceSize, SomeClass)] scStorage; |
December 16, 2016 Re: Allocating a class within another class during object init w/o passing in an allocator | ||||
---|---|---|---|---|
| ||||
Posted in reply to David Zhang | On Friday, 16 December 2016 at 18:25:42 UTC, David Zhang wrote: > I though all classes were aligned to sizeof(size_t) boundaries? I don't know. > Wouldn't it then just be > > align(sizeof(size_t)) byte[__traits(classInstanceSize, SomeClass)] scStorage; I guess? I really don't have much of a clue here. Looking around a bit, I found std.traits.classInstanceAlignment which seems fitting. http://dlang.org/phobos/std_traits.html#classInstanceAlignment |
Copyright © 1999-2021 by the D Language Foundation