删除char类型的un / / signedness

时间:2011-02-23 08:52:21

标签: c++ typetraits

我想专门为char,short,long和long long设计一个类模板。这种专业化也适用于整数类型的有符号和无符号变体。

我知道boost库和std :: tr1 / C ++ 0x实现了is_signed / is_unsigned和make_signed / make_unsigned type_traits。但是如何从char类型中删除任何已签名的规范(注意:签名itype!= itype的唯一整数类型)?

4 个答案:

答案 0 :(得分:4)

char的“sign-ness”是实现定义的。它不一定能够存储负数。在严格的标准中,char甚至从不是有符号整数类型,即使它可以在实现上存储负数。尽管如此,类模板is_signed会报告true char,如果它可以存储负数,因为这对它来说是有用的。

无论如何,提升文档会对make_unsigned进行以下说明,使其看起来像您可以将它用于您的目的。

  

如果T是无符号整数类型,则与T的类型相同,如果T是有符号整数类型,则为相应的无符号类型。否则,如果T是枚举或字符类型(char或wchar_t),则无符号整数类型与T具有相同的宽度

答案 1 :(得分:4)

非常手动且几乎没有任何魔法,但如果您要从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 );
}

答案 2 :(得分:0)

来自the source make_unsigned即使对char也应该仍然有用。你找不到了吗?如果您的平台上的char等同于unsigned char,那么它只对明确的signed char类型产生影响,这就是您想要的,对吗?

答案 3 :(得分:0)

好的,我找到了一个非常好看的解决方案:

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> */
/* ----------------------------------------------------------------------------------------------------- */