Hi! I am trying to figure out how to get the types of a key and a value in a map (knowing the type of a value of std.ArrayList would be nice as well ). The type information is needed to decode a slice of bytes into a given struct that could have arbitrary map or ArrayList types.
I thought I can do something like this, but I am getting error: struct 'hash_map.HashMapUnmanaged([]const u8,[]const u8,hash_map.StringContext,80).KV' has no member named 'key'. I would greatly appreciate any suggestions, thank you.
const std = @import("std");
pub fn main() void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
var m = std.hash_map.StringHashMap([]const u8).init(allocator);
defer m.deinit();
decode(@TypeOf(m));
}
fn decode(comptime T: type) void {
switch (@typeInfo(T)) {
.Struct => {
// What are the types of K and V in the map?
if (@hasDecl(T, "KV")) {
std.debug.print("{s}: key type {any}, value type = {any}", .{
@typeName(T),
T.KV.key,
T.KV.value,
});
}
},
else => unreachable,
}
}
This is because key is a field of KV, not a declaration, so you canโt just access it through the type, you need to inspect the fields via @typeInfo(T.KV). Hereโs an example using std.meta (which is a good reference for how to do reflection):
const std = @import("std");
pub fn main() void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
var m = std.hash_map.StringHashMap([]const u8).init(allocator);
defer m.deinit();
decode(@TypeOf(m));
}
fn decode(comptime T: type) void {
switch (@typeInfo(T)) {
.Struct => {
// What are the types of K and V in the map?
if (@hasDecl(T, "KV")) {
const Key = std.meta.FieldType(T.KV, .key);
const Value = std.meta.FieldType(T.KV, .value);
std.debug.print(
"{s}: key type {s}, value type = {s}",
.{ @typeName(T), @typeName(Key), @typeName(Value) },
);
}
},
else => unreachable,
}
}