将未知大小的整数转换为无符号形式的最短/最干净的方法?

时间:2014-12-20 06:01:57

标签: c++ integer-arithmetic

我正在编写一些代码来格式化十六进制数,目前它接受一个无符号的64位值。直到我意识到它格式化了一个带有太多符号扩展名的32位有符号整数,即“-1”变为“ffffffffffffffff”时,这一切都很好,很花哨。

我可以使用numeric_limits< T> :: digits:

来解决这个问题
template<class Int>
void Format(Int v) {
  switch(std::numeric_limits<Int>::digits) {
    case 7:
    case 8:
      CallFormatRoutine(0xFF & v);
    break;
    case 15:
    case 16:
      CallFormatRoutine(0xFFFF & v);
    break;
    case 31:
    case 32:
      CallFormatRoutine(0xFFFFFFFF & v);
    break;
    case 63:
    case 64:
      CallFormatRoutine(v);
    break;
  }
}

但我想知道是否有更好(更短)的方式。具体来说,这是一种适用于C ++ 03和C ++ 11的更好方法。理想情况下会有一些例程会返回你给它的任何整数的无符号版本,但我无法在标准中找到它。如果我可以使用C ++ 11,我可以写这个,虽然可能有一个强制转换,以避免有关签名/无符号转换的警告:

template<class Int>
void Format(Int v) {
  std::make_unsigned<Int>::type unsigned_v = v;
  CallFormatRoutine(unsigned_v);
}

有没有什么好的和简短的,这也适用于C ++ 03?

2 个答案:

答案 0 :(得分:2)

std::make_unsigned是实现您想要的最好和最短的方式,但您的示例中有一些错误。看起来应该是这样的:

template<class Int>
Format(Int v) {
  auto unsigned_v = static_cast<typename std::make_unsigned<Int>::type>(v);
  CallFormatRoutine(unsigned_v);
}

使用C ++ 14编译器,相关的行可以缩短为

auto unsigned_v = static_cast<std::make_unsigned_t<Int>>(v);

对于C ++ 03编译器,有boost::make_unsigned,或者您可以自己实现它,但这有点单调乏味,因为您需要处理所有内置类型。

template<typename T>
struct make_unsigned
{ typedef T type; };

template<>
struct make_unsigned<char>
{ typedef unsigned char type; };

template<>
struct make_unsigned<signed char>
{ typedef unsigned char type; };

同样,为shortint和其余整数类型添加专精。

答案 1 :(得分:0)

FWIW,我最后只使用sizeof而不是std :: numeric_limits,并使用static_cast而不是0xFFFFFFFF:

template<class Int>
void Format(Int v) {
  static_assert(sizeof(v) == 1 || sizeof(v) == 2 || sizeof(v) == 4 || sizeof(v) == 8,
                "Unknown integer type");
  CallFormatRoutine( sizeof(v) == 1 ? static_cast<uint8>(v)
                   : sizeof(v) == 2 ? static_cast<uint16>(v)
                   : sizeof(v) == 4 ? static_cast<uint32>(v)
                   : static_cast<uint64>(v);
}

(我试图将此评论发布到我的问题,但无法使多行代码正确格式化。)