Type T as an array index or hashmap key

This reminds me a bit of this topic:

related topics:


I think my preferred solution is to have something like this (if all your components are known at comptime):

const ManaComp = struct {};

const HpComp = struct {};

const NewComp = struct {}; // not registered yet

const ComponentId = enum(u32) { _ };
pub fn componentId(comptime ComponentType: type) ComponentId {
    // NOTE linear search here should be un-problematic unless you have a huge number of components
    // because the comptime result of this function is memoized anyway
    return @enumFromInt(comptime std.mem.findScalar(type, &components, ComponentType) orelse @compileError("please add missing Component: " ++ @typeName(ComponentType) ++ " to the components array"));
}
const components = [_]type{
    HpComp,
    ManaComp,
    // NewComp,
};

const std = @import("std");

pub fn main() !void {
    std.debug.print("HpComp id: {}\n", .{componentId(HpComp)});
    std.debug.print("ManaComp id: {}\n", .{componentId(ManaComp)});
    std.debug.print("NewComp id: {}\n", .{componentId(NewComp)});
}

A good question to ask yourself is whether you need components which are registered at runtime, if you don’t need them you can take advantage of simple comptime code like this, where you just add all components to this components array (getting an error if you forget) and you get a stable and reliable id for each component in return.

So basically this gives you a reliable index for your type, simply by enforcing that your type is part of this specific array that is used to determine / declare its index.