In the following topic opened by @zigo, we discussed using @constCast
patterns to deduplicate code in the style of Scott Meyers: Is it possible to apply const on return result adaptively? - #11 by AndrewCodeDev
It turns out, you can do this in Zig, but I’m trying to think of some more practical examples of what this could be used for (if anything). Here’s the simple version of the technique outlined in the original topic (please read it for for information):
fn isConstPtr(comptime T: type) bool {
return switch (@typeInfo(T)) {
.Pointer => |p| p.is_const, else => false
};
}
fn asConst(comptime T: type, value: *const T) @TypeOf(value) {
return value;
}
const Foo = struct {
value: usize = 0,
pub fn getPtr(self: anytype) @TypeOf(&self.value) {
if (comptime isConstPtr(@TypeOf(self))) {
// do some things you don't want to duplicate
return &self.value;
} else {
return @constCast(asConst(@This(), self).getPtr());
}
}
};
pub fn main() !void {
var bar = Foo{ .value = 42 };
const baz = Foo{ .value = 42 };
const bar_ptr = bar.getPtr();
const baz_ptr = baz.getPtr();
std.debug.print("Ptr Types: ({s}, {s})\n", .{
@typeName(@TypeOf(bar_ptr)),
@typeName(@TypeOf(baz_ptr)),
});
}
And this prints as expected:
Ptr Types: (*usize, *const usize)
I’ve been aware of the Meyers constCast pattern for years now, but I haven’t made much use of it, but this basically allows writing what is equivalent to an overloaded member function. I’d just like to see more examples and hear thoughts about where this may be useful?
Here’s a link to some more info on the topic: How to Share Code with Const and Non-Const Functions in C++ - C++ Stories
And here’s a blurb from that link:
Let’s reach out to Scott Meyers and in his Effective C++ 3rd Edition. On page 23, Item 3 (on using const) we can read that a non const function can safely call const one. To achieve this, we can leverage <const_cast>…
Does this assumption hold true in Zig? Anyhow, I’m curious to hear other people’s thoughts on this.