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
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.
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.