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)
当对应的类型不存在时,我会报错。
有没有办法在编译时将其映射到相应的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