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

Bee*_*ope 1 c++ template-meta-programming uint8t c++17

给定constexpr size 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
Run Code Online (Sandbox Code Playgroud)

当对应的类型不存在时,我会报错。

max*_*x66 5

有没有办法在编译时将其映射到相应的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>
 { };
Run Code Online (Sandbox Code Playgroud)

自定义类型是

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;
Run Code Online (Sandbox Code Playgroud)

以下是完整的编译示例

#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> );
 }
Run Code Online (Sandbox Code Playgroud)

如果愿意,可以修改st_helper以选择包含N字节的第一种类型,从而更改==in<=

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

这样,t24现在编译

   // now compile
   using t24 = selectType_t<24u, std::uint8_t, std::uint16_t,
                                 std::uint32_t, std::uint64_t>;
Run Code Online (Sandbox Code Playgroud)

并成为 std::uint32_t