Zig operator overloading types?

I was wondering if there (ever) will be - or is talked about - a kind of “my own dedicated descendant of a native zig type”, where we can implement functions for. Without having to wrap it inside a struct (which is of course always possible).

something like:

const Value = i32 {
    // my functions here
}

It is possible for integer types using non-exhaustive enum:

const Value = enum(i32) {
    _,

    // functions here
};
3 Likes

Oh! Never seen that one. I’ll experiment with that. Thanks.

Edit: not directly usable as a number :frowning:

Hm, I’m confused about how that is more convenient than a wrapper struct.

That is an advantage :slight_smile:

const std = @import("std");

const Value = enum(i32) {
    _,

    pub fn init(i: i32) Value {
        return @enumFromInt(i);
    }
};

test {
    const answer: Value = .init(42);
    try std.testing.expectEqual(42, @intFromEnum(answer));
}
1 Like

in the case of
enum(u8) {_}
it isnt,

but in the case of:

pub const Limit = enum(usize) {
    nothing = 0,
    unlimited = std.math.maxInt(usize),
    _,
}

You can have named values, that you can exhaustively switch on, i.e. the compiler will yell at you if you don’t handle nothing or unlimited. And you can differentiate between an else and _ branches. You can’t do that with the equivalent wrapper struct.

I understand. But that’s a different sort of need than just wanting to define a new type that’s equivalent to a primitive type and attach methods. For that I think a struct wrapper is the simplest and most convenient.

yes I would say a struct wrapper is slightly more convenient for this usecase.

My only concern about this usage is that it duplicates functionally with the packed struct and violates the principle of “There is only one solution”. I hope to get more opinions on the best practices here regarding when to use custom numbers constructed with such pure non-exhaustive enumerations and when to use packed struct that wraps only one field.