Question

I want to specialize a class template for char, short, long and long long. This specializations should also holds good for the signed and unsigned variants of the integral types.

I know boost library and std::tr1 / C++0x implements is_signed/is_unsigned and make_signed/make_unsigned type_traits. But how can I remove any signed specification from the char type (note: the only integral type where signed itype != itype)?

Was it helpful?

Solution

The "sign-ness" of char is implementation defined. It doesn't have to be able to store negative numbers. In strict standardese, char even is never a signed integer type, even if it can store negative numbers on an implementation. Still, the class template is_signed will report true for char if it can store negative numbers, because that's a useful thing for it to do.

Anyway, the boost docs say the following about make_unsigned, making it look like you can use it for your purpose.

If T is a unsigned integer type then the same type as T, if T is an signed integer type then the corresponding unsigned type. Otherwise if T is an enumerated or character type (char or wchar_t) then an unsigned integer type with the same width as T

OTHER TIPS

Quite manual and hardly any magic going on, but if you want to remove the signed/unsigned from a char, you can use this template:

template <typename T>
struct remove_sign_from_char {
   typedef T type;
};
template <>
struct remove_sign_from_char<signed char>
{
   typedef char type;
};
template <>
struct remove_sign_from_char<unsigned char>
{
   typedef char type;
};

int main() {
   static_assert( std::is_same< char, remove_sign_from_char<unsigned char>::type >::value );
   static_assert( std::is_same< char, remove_sign_from_char<signed char>::type >::value );
   static_assert( std::is_same< char, remove_sign_from_char<char>::type >::value );
   static_assert( std::is_same< int, remove_sign_from_char<int>::type >::value );
}

From the source make_unsigned should still work even on char. Did you find otherwise? If on your platform char is equivalent to unsigned char then it will only have an effect on the explicit signed char type, which is what you want, right?

Okay, I found a quite good looking solution:

template<typename itype, typename = void> struct my_typedef;
/* ----------------------------------------------------------------------------------------------------- */

template<>
struct my_typedef<char>
{
    typedef char          type;
    typedef signed char   signed_type;
    typedef unsigned char unsigned_type;
}; /* template<> struct my_typedef<char> */
/* ----------------------------------------------------------------------------------------------------- */

template<>
struct my_typedef<short>
{
    typedef short          type;
    typedef signed short   signed_type;
    typedef unsigned short unsigned_type;
}; /* template<> struct my_typedef<short> */
/* ----------------------------------------------------------------------------------------------------- */

template<>
struct my_typedef<long>
{
    typedef long          type;
    typedef signed long   signed_type;
    typedef unsigned long unsigned_type;
}; /* template<> struct my_typedef<long> */
/* ----------------------------------------------------------------------------------------------------- */

template<>
struct my_typedef<long long>
{
    typedef long long          type;
    typedef signed long long   signed_type;
    typedef unsigned long long unsigned_type;
}; /* template<> struct my_typedef<long long> */
/* ----------------------------------------------------------------------------------------------------- */

template<>
struct my_typedef<signed char>
{
    typedef my_typedef<char>::type          type;
    typedef my_typedef<char>::signed_type   signed_type;
    typedef my_typedef<char>::unsigned_type unsigned_type;
}; /* template<> struct my_typedef<signed char> */
/* ----------------------------------------------------------------------------------------------------- */

template<typename itype>
struct my_typedef<itype, typename std::enable_if<std::is_unsigned<itype>, void>::type>
{
    typedef typename my_typedef<typename std::make_signed<itype>::type>::type type;
    typedef typename my_typedef<typename std::make_signed<itype>::type>::type signed_type;
    typedef typename my_typedef<typename std::make_signed<itype>::type>::type unsigned_type;
}; /* template<typename> struct my_typedef<signed itype> */
/* ----------------------------------------------------------------------------------------------------- */
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top