Отображение от размера до соответствующего типа uintN_t - PullRequest
1 голос
/ 02 ноября 2019

Учитывая размер 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

IЯ в порядке с ошибкой, когда соответствующий тип не существует.

1 Ответ

5 голосов
/ 02 ноября 2019

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...