module pind.samples.ja.memory.memory_7; size_t sizeWithPadding(T)() { static if (is (T == class)) { const candidateAddr = __traits(classInstanceSize, T); } else { const candidateAddr = T.sizeof; } return cast(size_t)nextAlignedAddress(cast(T*)candidateAddr); } T * nextAlignedAddress(T)(T * candidateAddr) { import std.traits; static if (is (T == class)) { const alignment = classInstanceAlignment!T; } else { const alignment = T.alignof; } const result = (cast(size_t)candidateAddr + alignment - 1) / alignment * alignment; return cast(T*)result; } import std.stdio; import std.string; import core.memory; import std.conv; // ... struct Student { string name; int id; string toString() { return format("%s(%s)", name, id); } } void main() { /* この型に関する情報。 */ writefln("Student.sizeof: %#x (%s) bytes", Student.sizeof, Student.sizeof); writefln("Student.alignof: %#x (%s) bytes", Student.alignof, Student.alignof); string[] names = [ "Amy", "Tim", "Joe" ]; const totalSize = sizeWithPadding!Student() * names.length; /* すべてのStudentオブジェクト用の領域を確保する。 * * 警告! このスライスからアクセスできるオブジェクトは * まだ構築されていない; 適切に構築されるまで、 * これらのオブジェクトにアクセスしてはならない。 */ Student[] students = (cast(Student*)GC.calloc(totalSize))[0 .. names.length]; foreach (i, name; names) { Student * candidateAddr = students.ptr + i; Student * objectAddr = nextAlignedAddress(candidateAddr); writefln("address of object %s: %s", i, objectAddr); const id = 100 + i.to!int; emplace(objectAddr, name, id); } /* すべてのオブジェクトが構築され、使用可能になった。 */ writeln(students); }