英文:
How to get the field value in comptime in zig
问题
I want to make a deserializer in Zig. Now I could iterate the field information in comptime. But I want to get the field default value in struct. Is there a way to get them? For example, I want to get the zzzz
's value 100
in getIntOrDefault
.
const std = @import("std");
const meta = std.meta;
const trait = meta.trait;
const assert = std.debug.assert;
pub fn deserializeInto(ptr: anytype) !void {
const T = @TypeOf(ptr);
comptime assert(trait.is(.Pointer)(T));
const C = comptime meta.Child(T);
ptr.* = switch (C) {
[]const u8 => "test string",
else => switch (@typeInfo(C)) {
.Struct => try deserializeStruct(C),
.Int => try getIntOrDefault(C),
else => @compileError("Unsupported deserialization type " ++ @typeName(C) ++ "\n"),
},
};
}
pub fn getIntOrDefault(comptime T: type) !T {
return 2;
}
pub fn deserializeStruct(comptime T: type) !T {
var value: T = undefined;
inline for (meta.fields(T)) |struct_field| {
try deserializeInto(&@field(value, struct_field.name));
}
return value;
}
pub fn main() !void {
const T = struct {
wwww: []const u8,
zzzz: u32 = 100,
};
var v: T = undefined;
try deserializeInto(&v);
std.debug.print("zzzz value is {d}\n", .{v.zzzz});
}
(Note: Code comments and non-translatable parts have been removed as per your request.)
英文:
I want to make a deserializer in Zig. Now I could iterate the field information in comptime. But I want to get the field default value in struct. Is there a way to get them? For example, I want to get the zzzz
's value 100
in getIntOrDefault
.
const std = @import("std");
const meta = std.meta;
const trait = meta.trait;
const assert = std.debug.assert;
pub fn deserializeInto(ptr: anytype) !void {
const T = @TypeOf(ptr);
comptime assert(trait.is(.Pointer)(T));
const C = comptime meta.Child(T);
ptr.* = switch (C) {
[]const u8 => "test string",
else => switch (@typeInfo(C)) {
.Struct => try deserializeStruct(C),
.Int => try getIntOrDefault(C),
else => @compileError("Unsupported deserialization type " ++ @typeName(C) ++ "\n"),
},
};
}
pub fn getIntOrDefault(comptime T: type) !T {
return 2;
}
pub fn deserializeStruct(comptime T: type) !T {
var value: T = undefined;
inline for (meta.fields(T)) |struct_field| {
try deserializeInto(&@field(value, struct_field.name));
}
return value;
}
pub fn main() !void {
const T = struct {
wwww: []const u8,
zzzz: u32 = 100,
};
var v: T = undefined;
try deserializeInto(&v);
std.debug.print("zzzz value is {d}\n", .{v.zzzz});
}
答案1
得分: 3
默认值可通过@typeInfo(T).Struct.fields[...].default_value
访问,但它存储为对anyopaque
的指针,除非使用@ptrCast
进行类型转换,否则无法对其进行解引用,示例如下:
const std = @import("std");
pub fn main() !void {
const TestStruct = struct {
foo: u32 = 123,
};
std.log.info("{}", .{ TestStruct{} });
const foo_field = @typeInfo(TestStruct).Struct.fields[0];
std.log.info("field name: {}", .{ foo_field.name });
if (foo_field.default_value) |dvalue| {
const dvalue_aligned: *const align(foo_field.alignment) anyopaque = @alignCast(dvalue);
const value = @as(*const foo_field.type, @ptrCast(dvalue_aligned)).*;
std.log.info("default value: {}", .{ value });
}
}
打印结果:
$ zig build run
info: main.main.TestStruct{ .foo = 123 }
info: field name: foo
info: default value: 123
在Zig 0.10版本中,@ptrCast
的用法如下:
const dvalue_aligned = @alignCast(foo_field.alignment, dvalue);
const value = @ptrCast(*const foo_field.type, dvalue_aligned).*;
std.log.info("default value: {}", .{ value });
英文:
Zig 0.11+
The default value is available as @typeInfo(T).Struct.fields[...].default_value
. But it is stored as a pointer to anyopaque
, you won't be able to dereference it, unless you cast it with @ptrCast
like that:
const std = @import("std");
pub fn main() !void {
const TestStruct = struct {
foo: u32 = 123,
};
std.log.info("{}", .{ TestStruct{} });
const foo_field = @typeInfo(TestStruct).Struct.fields[0];
std.log.info("field name: {s}", .{ foo_field.name });
if (foo_field.default_value) |dvalue| {
const dvalue_aligned: *const align(foo_field.alignment) anyopaque = @alignCast(dvalue);
const value = @as(*const foo_field.type, @ptrCast(dvalue_aligned)).*;
std.log.info("default value: {}", .{ value });
}
}
It prints:
$ zig build run
info: main.main.TestStruct{ .foo = 123 }
info: field name: foo
info: default value: 123
Zig 0.10
The @ptrCast
usage used to look like this:
const dvalue_aligned = @alignCast(foo_field.alignment, dvalue);
const value = @ptrCast(*const foo_field.type, dvalue_aligned).*;
std.log.info("default value: {}", .{ value });
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论