Is there a way call a method shared by all union field types?

Such as

const std = @import("std");

const T = union {
	X: struct {
	   fn foo(_: @This()) void {}
	},
	Y: struct {
	   fn foo(_: @This()) void {}
	},
};

pub fn main() !void {
   var t: T = undefined;
   t.X = .{};
   t.foo(); // error: no field or member function named 'foo' in 'T'
}

Directly, no… but you could maybe do something like this…

const T = union(enum) {
	X: struct {
	   fn foo(_: @This()) void { std.debug.print("\nfoo X\n", .{}); }
	},
	Y: struct {
	   fn foo(_: @This()) void { std.debug.print("\nfoo Y\n", .{}); }
	},
    pub fn foo(self: @This()) void {
        switch (self) {
            .X => |x| x.foo(),
            .Y => |y| y.foo(),
        }
    }
};

pub fn main() !void {

    const t: T = .{ .X = .{ } };

    t.foo(); // prints "foo X"
}
2 Likes

This can currently be done by using an inline else in a switch statement.

switch(t) {
    inline else => |q| q.foo(),
}

The inline statement effectively tells the compiler to produce the following code.

switch(t) {
    .X => |x| x.foo(),
    .Y => |y| y.foo(),
}

Read more here: Easy Interfaces with Zig 0.10

10 Likes