Mapping an integral template parameter value onto a primitive type

假如想象 提交于 2019-12-01 11:57:38

I would not use C++17 if constexpr for this, instead I'd use template specialization, as it looks more declarative to me.

Something along the following lines:

template<size_t S> struct SizeToType {static_assert(S != S, "Wrong size"); };

template<> struct SizeToType<1> { using type = uint8_t; };
template<> struct SizeToType<2> { using type = uint16_t; };
template<> struct SizeToType<4> { using type = uint32_t; };
template<> struct SizeToType<8> { using type = uint64_t; };

template<size_t S>
using SizeToToTypeT = typename SizeToType<S>::type;

Adding more types would be just adding more specializations (one-liners) here.

Not a great solution... but just for fun...

I propose a type traits (with helper and using to select the internal type) that, given a number (the number of bytes) and a list of types select the first type of the list with sizeof() greater or equal (or nothing if there is no such type)

template <std::size_t, typename, typename = std::true_type>
struct sizeTypeH;

template <std::size_t Dim>
struct sizeTypeH<Dim, std::tuple<>, std::true_type>
 { };  // no type found

template <std::size_t Dim, typename T0, typename ... Ts>
struct sizeTypeH<Dim, std::tuple<T0, Ts...>,
                 std::integral_constant<bool, (sizeof(T0) >= Dim)>>
 { using type = T0; };

template <std::size_t Dim, typename T0, typename ... Ts>
struct sizeTypeH<Dim, std::tuple<T0, Ts...>,
                 std::integral_constant<bool, (sizeof(T0) < Dim)>>
   : public sizeTypeH<Dim, std::tuple<Ts...>>
 { };

template <std::size_t Dim, typename ... Ts>
struct sizeType : public sizeTypeH<Dim, std::tuple<Ts...>>
 { };

template <std::size_t Dim, typename ... Ts>
using sizeType_t = typename sizeType<Dim, Ts...>::type;

Now another using that, receiving a integer, call this type traits with the ordered list of intX_t types

template <std::size_t Dim>
using intType_t = sizeType_t<Dim, std::int8_t, std::int16_t, std::int32_t,
                             std::int64_t>;

In my platform I have that the following static_assert() are verified.

   using t8  = intType_t<1u>;
   using t16 = intType_t<2u>;
   using t32 = intType_t<4u>;
   using t64 = intType_t<8u>;

   static_assert( std::is_same<t8, std::int8_t>{}, "!" );
   static_assert( std::is_same<t16, std::int16_t>{}, "!" );
   static_assert( std::is_same<t32, std::int32_t>{}, "!" );
   static_assert( std::is_same<t64, std::int64_t>{}, "!" );

If, tomorrow, is introduced a int128_t, you can simply add it in intType_t using definition.

Attention, please: there is no guaranties that the preceding static_assert() are satisfied.

First of all because the standard guaranties that a byte is at least of 8 bits; but can be more that 8 bits. If a byte is of 16 bits, from

using t16 = intType_t<2u>;

you get a type of 32 bits.

Second because intX_t types are optionals.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!