Mapping an integral template parameter value onto a primitive type

后端 未结 2 857
陌清茗
陌清茗 2021-01-15 22:07

I want to map a number to a type. For this example I\'ll make a function that maps a sizeof() result onto a signed primitive type.

I am wondering if there is a bette

相关标签:
2条回答
  • 2021-01-15 22:17

    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.

    0 讨论(0)
  • 2021-01-15 22:31

    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.

    0 讨论(0)
提交回复
热议问题