从大小映射到相应的uintN_t类型

Mapping from a size to the corresponding uintN_t type

本文关键字:uintN 类型 映射      更新时间:2023-10-16

给定一个constexpr大小的N,是否有某种方法可以在编译时将其映射到相应的uintN_t类型,而无需编写我自己的详尽映射,例如:

template <size_t N>
struct size_to_type {};
template<>
struct size_to_type<8> { using type = uint8_t; };
template<>
struct size_to_type<16> { using type = uint16_t; };
// etc

当对应的类型不存在时,我可以处理错误。

是否有某种方法可以在编译时将其映射到相应的uintN_t类型,而无需编写我自己的详尽映射[?]

我能想象的最好的是一个类型特征,给定一个数字(大小(和一个类型列表(一个std::uintXX_t序列或你喜欢的(,选择第一个完全包含给定字节数的类型。

需要一些作品,但可用于不同类型的列表。

给定以下递归助手类

template <std::size_t N, typename T0, typename,
bool = (N == CHAR_BIT * sizeof(T0))>
struct st_helper;
template <std::size_t N, typename T0, typename Tpl>
struct st_helper<N, T0, Tpl, true>
{ using type = T0; };
template <std::size_t N, typename T0, typename T1, typename ... Ts>
struct st_helper<N, T0, std::tuple<T1, Ts...>, false>
: public st_helper<N, T1, std::tuple<Ts...>>
{ };
template <std::size_t N, typename T0>
struct st_helper<N, T0, std::tuple<>, false>
{ };

自定义类型为

template <std::size_t N, typename T0, typename ... Ts>
struct selectType : public st_helper<N, T0, std::tuple<Ts...>>
{ };
template <std::size_t N, typename ... Ts>
using selectType_t = typename selectType<N, Ts...>::type;

以下是的完整编译示例

#include <iostream>
#include <climits>
template <std::size_t N, typename T0, typename,
bool = (N == CHAR_BIT * sizeof(T0))>
struct st_helper;
template <std::size_t N, typename T0, typename Tpl>
struct st_helper<N, T0, Tpl, true>
{ using type = T0; };
template <std::size_t N, typename T0, typename T1, typename ... Ts>
struct st_helper<N, T0, std::tuple<T1, Ts...>, false>
: public st_helper<N, T1, std::tuple<Ts...>>
{ };
template <std::size_t N, typename T0>
struct st_helper<N, T0, std::tuple<>, false>
{ };
template <std::size_t N, typename T0, typename ... Ts>
struct selectType : public st_helper<N, T0, std::tuple<Ts...>>
{ };
template <std::size_t N, typename ... Ts>
using selectType_t = typename selectType<N, Ts...>::type;
int main ()
{
using t08 = selectType_t<8u,  std::uint8_t, std::uint16_t,
std::uint32_t, std::uint64_t>;
using t16 = selectType_t<16u, std::uint8_t, std::uint16_t,
std::uint32_t, std::uint64_t>;
using t32 = selectType_t<32u, std::uint8_t, std::uint16_t,
std::uint32_t, std::uint64_t>;
using t64 = selectType_t<64u, std::uint8_t, std::uint16_t,
std::uint32_t, std::uint64_t>;
// compilation error
//using t24 = selectType_t<24u, std::uint8_t, std::uint16_t,
//                              std::uint32_t, std::uint64_t>;
static_assert( std::is_same_v<t08, std::uint8_t> );
static_assert( std::is_same_v<t16, std::uint16_t> );
static_assert( std::is_same_v<t32, std::uint32_t> );
static_assert( std::is_same_v<t64, std::uint64_t> );
}

如果您愿意,您可以修改st_helper以选择第一个包含N字节的类型,更改<=中的==

template <std::size_t N, typename T0, typename,
bool = (N <= CHAR_BIT * sizeof(T0))>
struct st_helper;// ^^

通过这种方式,t24现在编译

// now compile
using t24 = selectType_t<24u, std::uint8_t, std::uint16_t,
std::uint32_t, std::uint64_t>;

成为std::uint32_t