Deducing the type of an integer by its compiletime value

Viewed 100

Using C++14, 17 or 20, I am passing two template parameters to a templated class: TSize and MaxSize.

TSize is the type of MaxSize. Obviously, both are known at compile time. TSize needs to be big enough to fit MaxSize.

template <typename TSize = uint8_t, TSize MaxSize = 15>
class Foo {};

How can I automatically deduce TSize by the value of MaxSize, so I have it automatically by just setting the value of MaxSize? i.e.:

if MaxSize<256 -> TSize=uint8_t
if MaxSize<65536 && MaxSize>255 -> TSize=uint16_t

Many thanks for your help!

2 Answers

You can use std::conditional to choose between two types based on a compiletime condition. And if you don't want to change Foo you'll need some indirection to pick the right type for Foo (maybe partial specialization would do as well):

#include<type_traits>

template <typename TSize = uint8_t, TSize MaxSize = 15>
class Foo {};

template <unsigned value>
using Size_t_impl = typename std::conditional<(value > 255),uint16_t,uint8_t>::type;

template <unsigned value>
using FooIndirect = Foo< Size_t_impl<value>,value>;

You can use something like this:

template<uintmax_t n>
using FittingUIntT = std::conditional_t<
    n <= UINT8_MAX, uint8_t, std::conditional_t<
    n <= UINT16_MAX, uint16_t, std::conditional_t<
    n <= UINT32_MAX, uint32_t, uint64_t
>>>;

Demo

Related