7 Jun 2024 • C++ tricks: STL-free type traits

I ended up not actually using these but it seemed a shame to throw them away so here they are for copy pasterity.

underlyling_type:

template< typename T >
constexpr bool IsSigned() { return int( T( -1 ) ) == -1; }

template< size_t N, bool Signed > struct MakeIntType;
template<> struct MakeIntType< 1, true > { using T = s8; };
template<> struct MakeIntType< 2, true > { using T = s16; };
template<> struct MakeIntType< 4, true > { using T = s32; };
template<> struct MakeIntType< 8, true > { using T = s64; };
template<> struct MakeIntType< 1, false > { using T = u8; };
template<> struct MakeIntType< 2, false > { using T = u16; };
template<> struct MakeIntType< 4, false > { using T = u32; };
template<> struct MakeIntType< 8, false > { using T = u64; };

template< typename E >
using UnderlyingType = MakeIntType< sizeof( E ), IsSigned< E >() >::T;

ADDENDUM: that breaks in some cases, the __underlying_type intrinsic works on all compilers.

numeric_limits:

template< typename T > constexpr T MaxInt;
template<> constexpr u8  MaxInt< u8  > = U8_MAX;
template<> constexpr u16 MaxInt< u16 > = U16_MAX;
template<> constexpr u32 MaxInt< u32 > = U32_MAX;
template<> constexpr u64 MaxInt< u64 > = U64_MAX;