I’m developing some tests for the add_signed MPL class that converts the type to its signed counterpart. It is defined as follows:
template<class T>
struct add_signed {
typedef T type;
};
template<>
struct add_signed<std::uint8_t> {
typedef std::int8_t type;
};
template<>
struct add_signed<std::uint16_t> {
typedef std::int16_t type;
};
template<>
struct add_signed<std::uint32_t> {
typedef std::int32_t type;
};
template<>
struct add_signed<std::uint64_t> {
typedef std::int64_t type;
};
While testing on different types I noticed that the following evaluates to true:
std::is_same<add_signed<uintptr_t>::type, intptr_t>::value // true
Similarly for the add_unsigned MPL class, the following code evaluates to true:
std::is_same<add_unsigned<intptr_t>::type, uintptr_t>::value // true
My compiler is MSVC 2010.
So the question is – can we assume that in all (sane) compilers signing intptr_t will produce uintptr_t and vice versa?
The types
intptr_tanduintptr_tare optional in ISO/IEC 9899:1999 (C99), but where one is implemented, so is the other. All signed types have an unsigned counterpart of the same size, and vice versa.Note that within the meaning of the C standard, functions are not objects; it is not guaranteed by the C standard that
uintptr_tcan hold a function pointer.Fortunately, POSIX steps to the rescue: it does require that object pointers and function pointers are the same size.