type-safe compare