Structs

11.1 Defining Structs (Value Types)

Structs live on the stack (or inline in other objects). There's no inheritance and no vtable. Allocate on the heap with new (Point* hp = new Point(1, 2);).

Default constructors (this()) aren't allowed. Use default member values or static factory functions (static Point opCall()).

struct Point
{
    double x = 0;             // default member value
    double y = 0;

    this(double x, double y)  // constructor
    {
        this.x = x;
        this.y = y;
    }

    double length() const     // const method: doesn't modify the instance
    {
        import std.math : sqrt;
        return sqrt(x * x + y * y);
    }

    void scale(double k) { x *= k; y *= k; }

    string toString() const
    {
        import std.format : format;
        return format("(%s, %s)", x, y);
    }
}

auto p = Point(3, 4);
Point q = { x: 1, y: 2 };     // static initializer (named fields)
p.scale(2);
writeln(p, " ", p.length);
auto r = p;                   // copied

11.2 Destructors and RAII

struct FileHandle
{
    import core.stdc.stdio : FILE, fopen, fclose;
    FILE* fp;
    this(string path) { fp = fopen(path.ptr, "r"); }
    ~this() { if (fp) fclose(fp); }   // runs deterministically at scope exit
    @disable this(this);              // disable copying (unique ownership)
}

11.3 Static Members and Nested Structs

struct Counter
{
    static int instances;     // thread-local static by default
    __gshared int global;     // truly global (shared, unsafe)
    shared static int sharedCount;
    static void reset() { instances = 0; }
    struct Inner { int v; }
}

11.4 Anonymous Structs, Tuples and Bitfields

import std.bitmanip : bitfields;
struct Flags
{
    mixin(bitfields!(
        bool, "read", 1,
        bool, "write", 1,
        uint, "mode", 6));
}
// Native bitfields: -preview=bitfields (newer compilers)