Allocation is not Initialization

I think, it’s even better to have both init and create “constructors”, like this:

const std = @import("std");
const Allocator = std.mem.Allocator;

const User = struct {
    domain: []const u8 = "ziggit.dev",
    enabled: bool = false,

    fn init(d: []const u8, e: bool) User {
        return .{.domain = d, .enabled  = e};
    }

    fn create(a: Allocator, d: []const u8, e: bool) !*User {
        var u = try a.create(User);
        u.* = init(d, e);
        return u;
    }
};

pub fn main() !void {
    const a = std.heap.c_allocator;
    const u_on_stack = User.init("dom1.org", true);
    const u_on_heap = try User.create(a, "dom2.org", true);

    std.debug.print(
        "user on stack : d = '{s}', e = {} ({*})\n",
        .{u_on_stack.domain, u_on_stack.enabled, &u_on_stack}
    );

    std.debug.print(
        "user on heap  : d = '{s}', e = {} ({*})\n",
        .{u_on_heap.domain, u_on_heap.enabled, u_on_heap}
    );
}

Note: compile with zig build-exe aini.zig -lc

This way we can conveniently use either stack allocated objects or heap allocated objects, depending on whatever is needed at the moment.

Output of the program:

$ ./aini 
user on stack : d = 'dom1.org', e = true (aini.User@7ffc6442dff0)
user on heap  : d = 'dom2.org', e = true @aini.User@4892a0)
6 Likes