If you want to do the manual approach, you can just define a declaration like so:
const MyEnum = enum(u32) {
a = 0,
b = 1,
c = 2,
pub const last: MyEnum = .c;
};
// Usage:
// const maximum: MyEnum = .last;
If you want a more general solution, @swenninger’s strategy is close, but isn’t quite complete. The order of the fields provided by @typeInfo is based on the order that they are declared in the file, not their values. So, you would need to check the value of every field and get the highest one:
pub fn greatestEnumTag(comptime Enum: type) Enum {
return comptime blk: {
const enum_info = @typeInfo(Enum).@"enum";
if (enum_info.fields.len == 0) {
@compileError("enum has no fields");
}
var max_value: enum_info.tag_type = enum_info.fields[0].value;
var max_name: []const u8 = enum_info.fields[0].name;
for (enum_info.fields[1..]) |field| {
if (field.value > max_value) {
max_value = field.value;
max_name = field.name;
}
}
break :blk @field(Enum, max_name);
};
}
EDIT: The above code can be simpler:
pub fn greatestEnumTag(comptime Enum: type) Enum {
return comptime blk: {
const enum_info = @typeInfo(Enum).@"enum";
if (enum_info.fields.len == 0) {
@compileError("enum has no fields");
}
var max_value: enum_info.tag_type = enum_info.fields[0].value;
for (enum_info.fields[1..]) |field| {
max_value = @max(max_value, field.value);
}
break :blk @enumFromInt(max_value);
};
}