Two points. 1) Currently, the code could be written with normal overloading (one for int and one for unsigned). No traits required. 2) The current code relies on an implicit cast to int or unsigned int. I’m not sure that’s good.
f( (uint8_t)0 ) will dispatch to the overload f(int) with overloads. The type-trait code will dispatch to f_unsigned(unsigned).