The emplace docs state that the chunk where to store the class object instance needs to be aligned to the class type alignment. But it doesn't say much on how to get this alignment from a class (we could add a note about using the classInstanceAlignment template), or even how to use it to create e.g. an array of class objects (not an array of references).
Here's how one can run into a problem: ----- import std.conv; class C { this(ubyte b) { _b = b; } ubyte _b; } void main() { // 9 bytes (x32), it's not going to align itself properly enum Size = __traits(classInstanceSize, C); ubyte[Size][2] buffer; // off-topic: cast needed -> yet another emplace bug auto obj1 = emplace!C(buffer[0], cast(ubyte)20); assert(obj1._b == 20); auto obj2 = emplace!C(buffer[1], cast(ubyte)20); // Boom! assert(obj2._b == 20); } ----- On the second emplace call, an exception is thrown: ----- std.conv.ConvException@std\conv.d(3832): emplace: Misaligned memory block (0x18FD41): it must be 4-byte aligned for type C ----- So one has to figure out how to do alignment properly, but there's no real documentation on how to do it. I had a look at the scoped() implementation for reference, but it's quite complex, here's a snippet: ----- template scoped(T) if (is(T == class)) { // _d_newclass now use default GC alignment (looks like (void*).sizeof * 2 for // small objects). We will just use the maximum of filed alignments. alias classInstanceAlignment!T alignment; alias _alignUp!alignment aligned; static struct Scoped { // Addition of `alignment` is required as `Scoped_store` can be misaligned in memory. private void[aligned(__traits(classInstanceSize, T) + size_t.sizeof) + alignment] Scoped_store = void; @property inout(T) Scoped_payload() inout { void* alignedStore = cast(void*) aligned(cast(size_t) Scoped_store.ptr); // As `Scoped` can be unaligned moved in memory class instance should be moved accordingly. immutable size_t d = alignedStore - Scoped_store.ptr; size_t* currD = cast(size_t*) &Scoped_store[$ - size_t.sizeof]; if(d != *currD) { import core.stdc.string; memmove(alignedStore, Scoped_store.ptr + *currD, __traits(classInstanceSize, T)); *currD = d; } return cast(inout(T)) alignedStore; } alias Scoped_payload this; @disable this(); @disable this(this); ~this() { // `destroy` will also write .init but we have no functions in druntime // for deterministic finalization and memory releasing for now. .destroy(Scoped_payload); } } /// Returns the scoped object @system auto scoped(Args...)(auto ref Args args) { Scoped result = void; void* alignedStore = cast(void*) aligned(cast(size_t) result.Scoped_store.ptr); immutable size_t d = alignedStore - result.Scoped_store.ptr; *cast(size_t*) &result.Scoped_store[$ - size_t.sizeof] = d; emplace!(Unqual!T)(result.Scoped_store[d .. $ - size_t.sizeof], args); return result; } } ---- It uses a private _alignUp helper template as well: ----- private size_t _alignUp(size_t alignment)(size_t n) if(alignment > 0 && !((alignment - 1) & alignment)) { enum badEnd = alignment - 1; // 0b11, 0b111, ... return (n + badEnd) & ~badEnd; } ----- There is a lot of magic here that's hard to understand. Anyway, since we already have emplace() as a public Phobos function, I thought it might be good if we had another overload which created an array of objects, or even a static array of objects wrapped in a convenient random access range on top. Otherwise guaranteeing alignment by hand seems to be complicated (judging from the scoped template implementation). I'm just pseudocoding here: ----- class Point { this(int x, int y) { _x = x; _y = y; } int _x; int _y; } void main() { // arr is a struct instance which holds the aligned static array, // which itself holds the Point objects. // The struct has opIndex, alias this, etc, to simulate // an array of references. auto arr = emplaceStaticArray!(Point, 2); // 2 items // note: one /could/ also allow calling the ctors in the above call, // although the syntax could be tricky arr[0].initialize(1, 2); // destroys existing state (if any), calls the ctor arr[1].initialize(3, 4); // ditto Point point = arr[0]; // get the object reference via alias this (just like in scoped) assert(point.x == 1 && point.y == 2); } ----- An equivalent emplaceArray for dynamic (resizable) arrays could also be implemented, where the memory can expand and shrink as necessary. Thoughts? I know bearophile is probably interested. :)