#include <iostream>
#include <limits>
#include <random>
#include <type_traits>

template <typename TYPE>
std::uniform_int_distribution<TYPE> getDice(std::true_type)
{
   return std::uniform_int_distribution<TYPE>(std::numeric_limits<TYPE>::min(), std::numeric_limits<TYPE>::max());
}

template <typename TYPE>
std::uniform_real_distribution<TYPE> getDice(std::false_type)
{
   return std::uniform_real_distribution<TYPE>(std::numeric_limits<TYPE>::min(), std::numeric_limits<TYPE>::max());
}

template<typename TYPE>
TYPE generateRandom()
{
   std::random_device randomDevice;
   std::mt19937_64 generator(randomDevice());
   auto dice = getDice<TYPE>(std::integral_constant<bool, std::numeric_limits<TYPE>::is_integer>());
   return dice(generator);
}

int main()
{
   float r1 = generateRandom<float>();
   double r2 = generateRandom<double>();
   int r3 = generateRandom<int>();
   long r4 = generateRandom<long>();

   std::cout << "r1: " << r1 << std::endl;
   std::cout << "r2: " << r2 << std::endl;
   std::cout << "r3: " << r3 << std::endl;
   std::cout << "r4: " << r4 << std::endl;
}

