假设我有一个整数类型T(有符号或无符号)。我想(在编译时)引用最小的整数类型(有符号或无符号),它可以保持,例如std::numeric_limits<T>::max()
加1(在非溢出的意义上,我的意思)。
这是一个很好的通用方法吗?
答案 0 :(得分:3)
对于无符号类型,这可以解决问题:
template <typename T>
constexpr unsigned size_in_bits() { return sizeof(T) * CHAR_BIT; }
template <typename T>
using smallest_larger_uint_t =
typename boost::uint_t<size_in_bits<T>() + 1>::least;
如果我们想要任何整数类型的东西:
template <typename T, int NumBits>
using boost_integer_type =
typename std::conditional<
std::is_unsigned<T>::value,
boost::uint_t<NumBits>,
boost::int_t<NumBits>
>::type;
template <typename T>
constexpr unsigned size_in_bits() { return sizeof(T) * CHAR_BIT; }
template <typename T>
using smallest_larger_integral_t =
typename boost_integer_type<T, size_in_bits<T>() + 1>::least;
有关int_t<N>
和uint_t<N>
的详细信息,请参阅documentation for Boost.Integer。
答案 1 :(得分:2)
您可以按所需大小指定整数并相应地选择:
#include <cstdint>
namespace Detail {
template <std::size_t> struct integer_of_size_undefined {};
template <> struct integer_of_size_undefined<sizeof(int8_t)> {
typedef int8_t type;
};
template <> struct integer_of_size_undefined<sizeof(int16_t)> {
typedef int16_t type;
};
template <> struct integer_of_size_undefined<sizeof(int32_t)> {
typedef int32_t type;
};
template <> struct integer_of_size_undefined<sizeof(int64_t)> {
typedef int64_t type;
};
template <std::size_t> struct unsigned_integer_of_size_undefined {};
template <> struct unsigned_integer_of_size_undefined<sizeof(int8_t)> {
typedef uint8_t type;
};
template <> struct unsigned_integer_of_size_undefined<sizeof(int16_t)> {
typedef uint16_t type;
};
template <> struct unsigned_integer_of_size_undefined<sizeof(int32_t)> {
typedef uint32_t type;
};
template <> struct unsigned_integer_of_size_undefined<sizeof(int64_t)> {
typedef uint64_t type;
};
}
template <std::size_t N>
struct integer_of_size {
typedef typename Detail::integer_of_size_undefined<N>::type type;
};
template <std::size_t N>
struct unsigned_integer_of_size {
typedef typename Detail::unsigned_integer_of_size_undefined<N>::type type;
};
#include <type_traits>
template <typename T>
struct next_integer {
typedef typename std::conditional<std::is_signed<T>::value,
typename std::make_unsigned<T>::type,
typename integer_of_size<2*sizeof(T)>::type>::type
type;
};
int main ()
{
static_assert(std::is_same<next_integer<std::int16_t>::type, uint16_t>::value,
"Should be a unsigned 16 bit");
static_assert(std::is_same<next_integer<std::uint16_t>::type, int32_t>::value,
"Should be a signed 32 bit");
return 0;
}
答案 2 :(得分:0)
您可以使用cstdint
中的类型
template <typename T>
struct next_type {
typedef error_type type;
};
template <>
struct next_type<std::int32_t> {
typedef std::uint32_t type;
}
template <>
struct next_type<std::uint32_t> {
typedef std::int64_t type;
}
// Add more...
为每种类型添加特化。然后使用它:
typename next_type<T>::type
因此,如果您已经使用了最大可能类型,那么您将获得error_type
,您必须以某种方式定义它自己的内容,否则需要专门化。
最好使用_least
中的cstdint
类型,例如std::int_least32_t
转到std::uint_least32_t
。
答案 3 :(得分:0)
如果你想在每个整数类型上都能很好地工作,你可以将它嵌入一个由几个步骤构建的特征中。我们首先使用位大小映射整数类型:
#define CREATE_SIGNED_META_OBJ(x) template <>\
struct signed_integer_type<x> {\
typedef int##x##_t type;\
};
#define CREATE_UNSIGNED_META_OBJ(x) template <>\
struct unsigned_integer_type<x> {\
typedef uint##x##_t type;\
};
template <std::size_t length>
struct signed_integer_type;
template <std::size_t len>
struct unsigned_integer_type;
CREATE_SIGNED_META_OBJ(8)
CREATE_SIGNED_META_OBJ(16)
CREATE_SIGNED_META_OBJ(32)
CREATE_SIGNED_META_OBJ(64)
CREATE_UNSIGNED_META_OBJ(8)
CREATE_UNSIGNED_META_OBJ(16)
CREATE_UNSIGNED_META_OBJ(32)
CREATE_UNSIGNED_META_OBJ(64)
然后,可以构建特征本身。我们想对断言std::numeric_limits<Int>::min() == 0
...
template <typename Int, bool>
struct get_smallest_for_max_plus_one;
template <typename Int>
struct get_smallest_for_max_plus_one<Int, true> {
typedef typename signed_integer_type<2*sizeof(Int)*8>::type type;
};
template <typename Int>
struct get_smallest_for_max_plus_one<Int, false> {
typedef typename unsigned_integer_type<sizeof(Int)*8>::type type;
};
template <typename Int>
using get_fittest_int_type = get_smallest_for_max_plus_one<Int, std::numeric_limits<Int>::min() == 0>;
现在我们可以直接使用get_fittest_int_type
和任何整数整数...可以在Coliru上找到运行示例。
为了保持一致性,我想你想要保留signed
或unsigned
属性......如果是这种情况,你可以用get_smallest_for_max_plus_one
替换// Unsigned type, we want to get the smallest unsigned type that can hold max + 1
template <typename Int>
struct get_smallest_for_max_plus_one<Int, true> {
typedef typename unsigned_integer_type<2*sizeof(Int)*8>::type type;
};
// Signed type, we want the smallest signed type that can hold max + 1
template <typename Int>
struct get_smallest_for_max_plus_one<Int, false> {
typedef typename signed_integer_type<2*sizeof(Int)*8>::type type;
};
的特化以下内容:
{{1}}