Allocating a generic struct in Zig lang

2.5k Views Asked by At

Is it possible to create allocation for struct that contains type as an attribute ?

For example

Example struct is

const Content = struct {
    content: type,
    name: []const u8,
};

Then, i would like to allocate memory for example of 2 * Content

I know i could use

const list: [2]CustomElement = .{ Content{ .content = Type, .name = "test" }, Content{ .content = Type, .name = "test" } };

But how to achieve them same thing using allocators ?

This doesn't work.

  comptime {
        var list = std.ArrayList(Content).init(test_allocator);
        try list.append(Content{ .content = MyType , .name = "test" });
    }

I get error

error: parameter of type '*std.array_list.ArrayListAligned(Content,null)' must be declared comptime

For short

Is it possible to build functionality for something like Box does in Rust ?

1

There are 1 best solutions below

2
On

From my understanding, I don't think the allocators currently available in the language (0.6.0 at the time of writing), which usually require a 'comptime` type parameter, currently permit this.

From the current documentation relating to comptime, concerning the type type:

In Zig, types are first-class citizens. They can be assigned to variables, passed as parameters to functions, and returned from functions. However, they can only be used in expressions which are known at compile-time, which is why the parameter T in the above snippet must be marked with comptime.

It does seem like something that should be possible, in that I think type must have a size, and you could probably allocate a structure that could hold it.

It does look like the comptime allocation is a use case that might be supported in upcoming versions: https://github.com/ziglang/zig/issues/1291, but I'm not sure how that would interact with type.

I'm a fairly new to Zig, so hopefully someone will provide a more complete answer =D

Edit: I'm sure it isn't the question you're asking, but if, like in the example above, you're only storing objects with the same type in the list, I guess you could do something with generics?

e.g.

const std = @import("std");

pub fn main() anyerror!void {
    const cw = ContentWrapper(MyType);

    var list = std.ArrayList(cw.Content).init(std.heap.page_allocator);
    try list.append(cw.Content{ .content = MyType{ .id = 1, .property = 30 }, .name = "First" });
    try list.append(cw.Content{ .content = MyType{ .id = 2, .property = 10 }, .name = "Second" });
}

const MyType = struct {
    id: u8, property: f32
};

fn ContentWrapper(comptime T: type) type {
    return struct {
        pub const Content = struct {
            content: T, name: []const u8
        };
    };
}