我有点晚了,但是...
#include <cstdint>
#include <cstdio>
#include <tuple>
template<uint64_t data, int8_t test_bit= sizeof(data)-1>
struct getMinimalByteSize{
using type= typename std::conditional< (bool)(data & (uint64_t)0xFFL << (test_bit*8)),
typename std::tuple_element_t<test_bit, std::tuple<uint8_t, uint16_t, uint32_t, uint32_t, uint64_t, uint64_t, uint64_t, uint64_t>>,
typename getMinimalByteSize<data, test_bit - 1>::type>::type;};
template<uint64_t data>
struct getMinimalByteSize<data, -1>{using type = uint64_t;};
int main()
{
static_assert(sizeof(getMinimalByteSize<0x0>::type)==8);
static_assert(sizeof(getMinimalByteSize<0xFF>::type)==1);
static_assert(sizeof(getMinimalByteSize<0xFFF>::type)==2);
static_assert(sizeof(getMinimalByteSize<0xFFFFF>::type)==4);
static_assert(sizeof(getMinimalByteSize<0xFFFFFFFFF>::type)==8);
}
与所有其他方法的区别在于测试。它不是测试该值是否大于给定 N 位可能的最大数字,而是逐个字节地测试它是否是最后一个(最重要的)非零字节。如果是,那么这是所需的最小位数。最后,我们使用手工制作的列表来修复 C++ 中没有定义 24、48、56 位整数的事实。
这就是这个模板元程序看起来像一个简单的 C 函数的样子:
#include <stddef.h>
int tuple_element_t[]={8,16,32,32,64,64,64,64,64};
int getMinimalByteSize(uint64_t data, int8_t first_hi_byte = sizeof(data)-1){
if (!data) return 0;
/* Does the N bit of test is set? If so, we are done*/
if (data & (uint64_t)0xFFL << (first_hi_byte*8))
return tuple_element_t[first_hi_byte];
else/*Else, we tray with the next bit*/
return getMinimalByteSize(data, first_hi_byte-1);}
如果您没有第一次看到它,请不要担心,给自己时间。我在 AVR 上工作了 10 多年,在一个每个字节都很重要的平台上。如果你在不到 10 年的时间里理解它,你就已经打败了我。