9

我需要在编译时找出可以表示特定数字的最小无符号整数类型。像这样的东西...

//////////////////////////////////////////////////////////////////////////
template<size_t Bits>
struct uint_least{};

template<>
struct uint_least<8>{ typedef std::uint8_t type; };

template<>
struct uint_least<16>{ typedef std::uint16_t type; };

//////////////////////////////////////////////////////////////////////////
template<size_t max>
struct uint_least_bits
{
    static const size_t value = 14; // just a placeholder
};

//////////////////////////////////////////////////////////////////////////
template<size_t max>
class A
{
    typedef typename uint_least<uint_least_bits<max>::value>::type underlying_type;

    underlying_type m_X;
};

uint_least旨在为您提供至少Bits大的最小无符号整数类型,它应该适用于高达 64 的任何值(不仅仅是 8、16、32、64,还有 1、4、13 等)。

uint_least_bits旨在为您提供表示max.

  • 我该如何实施uint_least
  • 我该如何实施uint_least_bits
  • 应该bits、、minmax是什么类型?如果答案是模板类型,我该如何防范无效输入?

特征的确切结构并不重要。随意废弃我提供的内容。我只需要提供一个数字并取回可以容纳它的最小无符号整数类型。

4

2 回答 2

9

我昨天刚做的,真是巧合。我会把它留在这里,即使它不完全是你所需要的(无论如何它修复了最好的整数类型):

#include <type_traits>
#include <stdint.h>

template<size_t i>
struct best_type {
    typedef typename std::conditional<
        (i <= 8),
        uint8_t,
        typename std::conditional<
            (i <= 16),
            uint16_t,
            typename std::conditional<
                (i <= 32),
                uint32_t,
                uint64_t
            >::type
        >::type
    >::type type;
};

然后,你会像这样使用它:

#include <type_traits>
#include <iostream>
#include <stdint.h>

template<size_t i>
struct best_type {
    typedef typename std::conditional<
        (i <= 8),
        uint8_t,
        typename std::conditional<
            (i <= 16),
            uint16_t,
            typename std::conditional<
                (i <= 32),
                uint32_t,
                uint64_t
            >::type
        >::type
    >::type type;
};   

int main() {
    std::cout << sizeof(best_type<2>::type) << std::endl;
    std::cout << sizeof(best_type<8>::type) << std::endl;
    std::cout << sizeof(best_type<15>::type) << std::endl;
    std::cout << sizeof(best_type<17>::type) << std::endl;
}

现场演示,在这里

于 2012-08-23T00:13:49.223 回答
4

如果你有constexpr,这将工作:

#include <climits>
#include <cstdint>
#include <cstddef>

inline
constexpr
unsigned
clz(unsigned x)
{
    return x == 0 ? sizeof(x)*CHAR_BIT : x & 0x80000000 ? 0 : 1 + clz(x << 1);
}

inline
constexpr
unsigned
clp2(unsigned x)
{
    return x == 0 ? 0 : 1 << (sizeof(x)*CHAR_BIT - clz(x-1));
}

inline
constexpr
unsigned
at_least8(unsigned x)
{
    return x < 8 ? 8 : x;
}

template<size_t Bits>
struct uint_least{};

template<>
struct uint_least<8>{ typedef std::uint8_t type; };

template<>
struct uint_least<16>{ typedef std::uint16_t type; };

template<>
struct uint_least<32>{ typedef std::uint32_t type; };

template<>
struct uint_least<64>{ typedef std::uint64_t type; };

template<size_t max>
struct uint_least_bits
{
    static const size_t value = clp2(max);
};

template<size_t max>
class A
{
    typedef typename uint_least<at_least8(uint_least_bits<max>::value)>::type underlying_type;

    underlying_type m_X;
};

int main()
{
    A<3> a;
}

如果你没有constexpr,你可以将 clp2 翻译成一个模板元函数(这留给读者练习:-))。

哦,免责声明:假设 32 位unsigned. 如果需要,这也可以概括。

于 2012-08-23T00:05:08.643 回答