here’s a generic function that wraps an array slice:
ArrayWrapper(T: type, a: []const T) type {
const _arr: []const T = a;
pub fn unwrap(_: @This()) []const T {
return _arr;
}
}
i 'd like to create a variant which actually embeds the array within the returned struct
… when ArrayWrapper
is called, i’ll presumably pass some appropriate initialization value (slice or array)…
but how does my generic function “know” the size of the embedded array which will now sit in a var _arr
decl???
alternatively, could i build a wrapper around a []T
slice which can be unwrapped and manipulated at run-time…
like the inlays from zls, i wish i could somehow declare [?]T
…
If you’re trying to go from a slice to an array, then it needs to be a comptime slice.
// copy a comptime slice to an array
pub fn sliceToArray(comptime s: []const u8) [s.len]u8 {
return s[0..].*;
}
The reasoning is fairly simple - since a slice is a fat pointer, it specifically can have variable lengths whereas arrays need a fixed size.
Otherwise, you need to inject comptime information (such as the size).
Addendum: You can also do something similar if you have a comptime size and a slice… s[0..N].*
where N is comptime known. This is handy for building @Vector
objects.
1 Like
Here’s an example which incorporates @AndrewCodeDev 's recommendations:
const std = @import("std");
fn ArrayWrapper(
comptime T: type,
comptime N: usize,
array: [N]T,
) type {
return struct {
array: [N]T = array,
const Self = @This();
fn unwrap(self: Self) [N]T {
return self.array;
}
};
}
pub fn main() !void {
const array = [_]u8{ 1, 2, 3 };
// Use the array directly.
const aw1 = ArrayWrapper(u8, 3, array){};
std.debug.print("{}\n", .{@TypeOf(aw1.unwrap())});
// Use a slice to obtain an array by slicing with
// comptime known length and then dereferencing
// the pointer.
const aw2 = ArrayWrapper(u8, 2, array[0..2].*){};
std.debug.print("{}\n", .{@TypeOf(aw2.unwrap())});
}
❯ zig build run
[3]u8
[2]u
anytype
is usefull for arrays.
fn ArrayWrapper(a: anytype) type {
const T = @typeInfo(@TypeOf(a)).Array.child;
const _arr: [a.len]T = a;
...
}
Are you trying to something like this in C?
struct line {
int length;
char contents[0];
};
I don’t think that’s possible in Zig.