Automatically pick a variable type big enough to hold a specified number
Sure, it's possible. Here are the ingredients. Let's start with my two favorite meta-functions:
template<uint64_t N>
struct constant
{
enum { value = N };
};
template<typename T>
struct return_
{
typedef T type;
};
Then, a meta-function that counts the bits required to store a number:
template<uint64_t N>
struct bitcount : constant<1 + bitcount<(N>>1)>::value> {};
template<>
struct bitcount<0> : constant<1> {};
template<>
struct bitcount<1> : constant<1> {};
Then, a meta-function that counts the bytes:
template<uint64_t N>
struct bytecount : constant<((bitcount<N>::value + 7) >> 3)> {};
Then, a meta-function that returns the smallest type for a given number of bytes:
template<uint64_t N>
struct bytetype : return_<uint64_t> {};
template<>
struct bytetype<4> : return_<uint32_t> {};
template<>
struct bytetype<3> : return_<uint32_t> {};
template<>
struct bytetype<2> : return_<uint16_t> {};
template<>
struct bytetype<1> : return_<uint8_t> {};
And finally, the meta-function that you asked for:
template<uint64_t N>
struct Integer : bytetype<bytecount<N>::value> {};
Boost.Integer already has facilities for Integer Type Selection:
boost::int_max_value_t<V>::least
The smallest, built-in, signed integral type that can hold all the values in the inclusive range 0 - V. The parameter should be a positive number.
boost::uint_value_t<V>::least
The smallest, built-in, unsigned integral type that can hold all positive values up to and including V. The parameter should be a positive number.