#include <iostream>
#include <typeinfo>
typedef signed char int8_t;
typedef short int16_t;
typedef int int32_t;
typedef long long int64_t;
static int8_t const min8 = -128;
static int8_t const max8 = 127;
static int16_t const min16 = -32768;
static int16_t const max16 = 32767;
static int32_t const min32 = -2147483648LL;
static int32_t const max32 = 2147483647;
/**
* Helper for IntTypeThatFits.
* Template parameters indicate whether the given number fits into 8, 16 or 32
* bits. If neither of them is true, it is assumed that it fits 64 bits.
*/
template <bool fits8, bool fits16, bool fits32>
struct IntTypeThatFitsHelper { };
// specializations for picking the right type
// these are all valid combinations of the flags
template<> struct IntTypeThatFitsHelper<true, true, true> { typedef int8_t Result; };
template<> struct IntTypeThatFitsHelper<false, true, true> { typedef int16_t Result; };
template<> struct IntTypeThatFitsHelper<false, false, true> { typedef int32_t Result; };
template<> struct IntTypeThatFitsHelper<false, false, false> { typedef int64_t Result; };
/// Finds the smallest integer type that can represent the given number.
template <int64_t n>
struct IntTypeThatFits
{
typedef typename IntTypeThatFitsHelper<
(n <= max8) && (n >= min8),
(n <= max16) && (n >= min16),
(n <= max32) && (n >= min32)
>::Result Result;
};
template <typename X, typename Y>
void print_impl(Y y) { std::cout << y << ": " << typeid(X).name() << "\n"; }
template <int64_t n>
void print() {
typedef typename IntTypeThatFits<n>::Result Result;
print_impl<Result>(n);
}
int main() {
print_impl<int8_t>("int8_t");
print_impl<int16_t>("int16_t");
print_impl<int32_t>("int32_t");
print_impl<int64_t>("int64_t");
print<56>();
print<-128>();
print<9832586235>();
}