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