I am having some trouble creating functions returning const or mutable stuff without duplicating code. This affects the way to write iterators as well.
Let’s take a simplified image example.
Sometimes I want readonly access, sometimesj mutable access.
How to handle this?
And while writing this thread I was wondering about the 3d function. Is that legal, the image being const and returning a mutable slice?
In this case, we only need get_line_slice_3 because the pixels field is just a slice (pointer).
*const Image only prevents modifying the Image object itself through that pointer. Constness is not transitive through the pointer stored in the pixels field, so it is perfectly valid for get_line_slice_3 to return a mutable []Pixel .
Of course, if pixels were an array instead of a slice, things would get a lot trickier.
But that’s why it’s an issue. For array field just a little meta programming on the input constness is enough. Here the problem is how should I encode constness for my “slice wrapper” type.
Zig has power here that library authors don’t have, because []u8 silently casts to []const u8, while MyMutSlice wont cast to MyConstSlice
The way I usually handle this is by only writing the const version of the function. Then, you can handle the mutable case by using @constCastat the callsite. The rule here is that if you pass in mutable data, then you’re allowed to use @constCast on whatever you get back.
I tried your approach at some point, but in the end I decided it wasn’t worth the hassle. In practice const/non constness is relatively easy to track down, compared to eg ownership where the type system don’t help. We already have type safety to track host memory vs accelerator memory, so I didn’t want to multiply the nber of combintions.