Удалить не подпись / подпись типа char - PullRequest
1 голос
/ 23 февраля 2011

Я хочу специализировать шаблон класса для char, short, long и long long. Эта специализация также подходит для подписанных и беззнаковых вариантов целочисленных типов.

Я знаю, что библиотека boost и std :: tr1 / C ++ 0x реализуют is_signed / is_unsigned и make_signed / make_unsigned type_traits. Но как я могу удалить любую подписанную спецификацию из типа char (примечание: единственный целочисленный тип со знаком itype! = Itype)?

Ответы [ 4 ]

4 голосов
/ 23 февраля 2011

Довольно ручная работа и почти не происходит никакой магии, но если вы хотите удалить signed / unsigned из char, вы можете использовать этот шаблон:

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 );
}
4 голосов
/ 23 февраля 2011

«Знак» char определяется реализацией. Это не должно быть в состоянии хранить отрицательные числа. В строгом стандарте char даже является никогда целочисленным типом со знаком, даже если он может хранить отрицательные числа в реализации. Тем не менее, шаблон класса is_signed сообщит true для char, если он может хранить отрицательные числа, потому что это полезная вещь для этого.

Как бы то ни было, в документах о повышении сказано следующее о make_unsigned, и похоже, что вы можете использовать его для своих целей.

Если T является целым типом без знака, то тот же тип, что и T, если T является целочисленным типом со знаком, то соответствующий тип без знака. В противном случае, если T является перечислимым или символьным типом (char или wchar_t), тогда целочисленный тип без знака с той же шириной, что и T

0 голосов
/ 23 февраля 2011

Хорошо, я нашел довольно привлекательное решение:

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> */
/* ----------------------------------------------------------------------------------------------------- */
0 голосов
/ 23 февраля 2011

С источник make_unsigned должен работать даже на char.Вы нашли иначе?Если на вашей платформе char эквивалентно unsigned char, то это повлияет только на явный тип signed char, что вам и нужно, верно?

...