Behaviour of @typeName()

So i want to check whether two types are the same (one type is a runtime stored *const [:0]u8, where the other is a comptime “type” function argument) so basically this

pub fn isTheSame(self: Self, comtime x: type) bool{
    ///now i want to check if the comptime x of type is the same as the runtime stored type in self
    if  (self.described_type == @typeName(x)){
        return true;
    }
    return false;
}

I am uncertain whether this would work because here i am checking a pointer to the type name not the name itself, also i would like to not check the name character by character because this function will be invoked very often in a realtime application (although i know that checking even 100 character strings for equality is pretty much nothing for a modern computer)

Never rely on the output of @typeName: its return value will more than likely end up being implementation-defined (if @typeName isn’t removed from the language altogether, that is).

The issue with @typeName is simply that its behaviour (i.e. the string it returns) is necessarily implementation-defined and cannot be codified in a language specification, because we cannot reasonably standardise the compiler’s approach to generating names for types which don’t have an obvious user-provided name. The concern is that some codebases already use @typeName in a way which relies heavily on how our compiler generates type names, so in the future this would be likely to lead to Zig projects which do not compile on other compiler implementations, which is a bad experience for all involved.

https://codeberg.org/ziglang/zig/issues/32119#issuecomment-13988375

You can find typeid method from @mlugg in first link and it would be preferred way to do that. Copying it here for convenience:

const std = @import("std");

const TypeId = *const struct {
    _: u8,
};

pub inline fn typeId(comptime T: type) TypeId {
    return &struct {
        comptime {
            _ = T;
        }
        var id: @typeInfo(TypeId).pointer.child = undefined;
    }.id;
}

pub fn main() !void {
    @compileLog(typeId(u8) == typeId(u8)); // comptime-known
    @compileLog(typeId(u8) == typeId(u16)); // and works correctly
    @compileLog(typeId(u16) == typeId(u16));
    passAtRuntime(typeId(u8), typeId(u16));
}

fn passAtRuntime(a: TypeId, b: TypeId) void { // and you can pass them at runtime too
    _ = a;
    _ = b;
}

Thanks a lot for the fast reply, to give a bit of background of what i am doing, Im trying to make a game engine, and currently writing some code to deal with storing collections of objects, because each object type has to be stored in a different collection. when researching i thought that the typeName approach is clunky, so i searched on the internet for a better solution and i found the discussion you linked to, but to be honest i didnt use it because i didnt like the weird code that it uses and chose to use typeName instead, but with the things you pointed out i think i will use the typeID solution though. I just dont understand why there isnt such a bultin as typeID

Seems like you doing something akin to ECS so here is also a link to type_id used for that kind of task. https://codeberg.org/Games-by-Mason/mr_ecs/src/branch/main/src/type_id.zig

thanks for the help, but i dont plan on making an ECS, its going to be something similar but not really.

1 Like