есть ли способ сопоставить его во время компиляции с соответствующим типом 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