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

标签 c++ c++17 template-meta-programming uint8t

给定一个 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

当相应的类型不存在时,我可以接受错误。

最佳答案

is there some way to map it at compile-time to the corresponding uintN_t type, without writing my own exhaustive mapping [?]

我能想象的最好的是一个类型特征,给定一个数字(大小)和一个类型列表(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

关于c++ - 从大小映射到相应的 uintN_t 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58673950/

相关文章:

c# - 将字符串数组从 C# 传递到 C++ dll,然后再返回

c++ - 为什么是 "move semantics"而不是简单的 memcpy?

c++ - 表达式f()>g()的值,当f&g修改同一个全局变量undefined或unspecified时?

c++ - 通过显式调用其析构函数和构造函数来重新创建对象

c++ - 将 lambda 绑定(bind)到函数以获得返回结果

c++ - qt 应用程序未运行

c++ - 从 boost python 模块内的 pyside 导入类?

c++ - 提升灵弦属性兼容性

c++ - boost::mpl::or_ 和 boost::mpl::and_ 的不同行为?

c++ - 使用元编程和可变参数模板填充静态模板化数组